mirror of
https://github.com/jie65535/JChatGPT.git
synced 2026-02-02 20:18:10 +08:00
Compare commits
2 Commits
ec358fd852
...
c4afdb811b
| Author | SHA1 | Date | |
|---|---|---|---|
| c4afdb811b | |||
| 9094f6c8db |
497
src/main/java/com/github/heqiao2010/lunar/LunarCalendar.java
Normal file
497
src/main/java/com/github/heqiao2010/lunar/LunarCalendar.java
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
package com.github.heqiao2010.lunar;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中国农历
|
||||||
|
* Created by joel on 2019/3/31.
|
||||||
|
*
|
||||||
|
* @author joel
|
||||||
|
*/
|
||||||
|
public class LunarCalendar extends GregorianCalendar {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* serialVersionUID
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 7241031233810655166L;
|
||||||
|
|
||||||
|
// ------------------------ 农历相关成员变量 --------------------------------
|
||||||
|
|
||||||
|
// 农历年,和公历可能不一样
|
||||||
|
private int lunarYear;
|
||||||
|
// 农历月(范围1-12和公历不一样)
|
||||||
|
private int lunarMonth;
|
||||||
|
// 农历日期
|
||||||
|
private int dayOfLunarMonth;
|
||||||
|
// 是否为闰月日期
|
||||||
|
private boolean isLeapMonth = false;
|
||||||
|
// 农历这年闰月,如果不闰月,默认为0
|
||||||
|
private int leapMonth = 0;
|
||||||
|
|
||||||
|
// ------------------------ 构造方法 --------------------------------
|
||||||
|
|
||||||
|
public LunarCalendar() {
|
||||||
|
super();
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LunarCalendar(TimeZone zone) {
|
||||||
|
super(zone);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LunarCalendar(Locale aLocale) {
|
||||||
|
super(aLocale);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LunarCalendar(TimeZone zone, Locale aLocale) {
|
||||||
|
super(zone, aLocale);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过公历年、月、日构造
|
||||||
|
* @param year 公历年
|
||||||
|
* @param month 公历月
|
||||||
|
* @param dayOfMonth 公历日
|
||||||
|
*/
|
||||||
|
public LunarCalendar(int year, int month, int dayOfMonth) {
|
||||||
|
super(year, month, dayOfMonth);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LunarCalendar(int year, int month, int dayOfMonth, int hourOfDay, int minute) {
|
||||||
|
super(year, month, dayOfMonth, hourOfDay, minute);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LunarCalendar(int year, int month, int dayOfMonth, int hourOfDay, int minute, int second) {
|
||||||
|
super(year, month, dayOfMonth, hourOfDay, minute, second);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过农历年、月、日构造
|
||||||
|
*
|
||||||
|
* @param lunarYear 农历年
|
||||||
|
* @param lunarMonth 农历月份,范围1-12
|
||||||
|
* @param dayOfLunarMonth 农历日
|
||||||
|
* @param isLeapMonth 是否闰月
|
||||||
|
*/
|
||||||
|
public LunarCalendar(int lunarYear, int lunarMonth, int dayOfLunarMonth, boolean isLeapMonth) {
|
||||||
|
computeByLunarDate(lunarYear, lunarMonth, dayOfLunarMonth, isLeapMonth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过公历构造
|
||||||
|
*
|
||||||
|
* @param calendar 公历日期
|
||||||
|
*/
|
||||||
|
public LunarCalendar(Calendar calendar) {
|
||||||
|
super(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
|
||||||
|
calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------ 静态方法 --------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公历转农历
|
||||||
|
*
|
||||||
|
* @param solar 公历日期
|
||||||
|
* @return 农历日期
|
||||||
|
*/
|
||||||
|
public static LunarCalendar solar2Lunar(Calendar solar) {
|
||||||
|
return new LunarCalendar(solar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历转公历
|
||||||
|
*
|
||||||
|
* @param lunarYear 农历年
|
||||||
|
* @param lunarMonth 农历月,从1开始
|
||||||
|
* @param LunarDate 农历日
|
||||||
|
* @param isLeapMonth 是否润月
|
||||||
|
* @return 公历日期
|
||||||
|
*/
|
||||||
|
public static Calendar lunar2Solar(int lunarYear, int lunarMonth, int LunarDate, boolean isLeapMonth) {
|
||||||
|
LunarCalendar ret = new LunarCalendar();
|
||||||
|
ret.computeByLunarDate(lunarYear, lunarMonth, LunarDate, isLeapMonth);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------ 成员方法 --------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公历上的操作,加减均是公历上的“一年”,“一个月”
|
||||||
|
* @param field {@link java.util.Calendar} YEAR/MONTH/DATE
|
||||||
|
* @param amount 数量,可正可负
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void add(int field, int amount) {
|
||||||
|
super.add(field, amount);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历上的年月日,加减均是农历上的“一年”,“一个月”
|
||||||
|
* @param field {@link java.util.Calendar} YEAR/MONTH/DATE
|
||||||
|
* @param amount 数量,可正可负
|
||||||
|
*/
|
||||||
|
public void addByLunar(int field, int amount) {
|
||||||
|
switch (field) {
|
||||||
|
case Calendar.DATE:
|
||||||
|
super.add(Calendar.DATE, amount);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
break;
|
||||||
|
case Calendar.MONTH:
|
||||||
|
addLunarMonths(amount);
|
||||||
|
break;
|
||||||
|
case Calendar.YEAR:
|
||||||
|
// 增加一个农历年,保持月/日不变,清空闰月状态
|
||||||
|
checkComputeLunarDate(lunarYear + amount, lunarMonth, dayOfLunarMonth, false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(String.format("unsupported field: %d", field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算月份加减
|
||||||
|
*
|
||||||
|
* @param amount 数量
|
||||||
|
*/
|
||||||
|
public void addLunarMonths(int amount) {
|
||||||
|
int y = lunarYear;
|
||||||
|
int m = -1;
|
||||||
|
int index = LunarCodes.monthIndex(y, lunarMonth, isLeapMonth);
|
||||||
|
boolean isLeapMonth = false;
|
||||||
|
int sum = index + amount;
|
||||||
|
if (amount > 0) {
|
||||||
|
for (int _y = lunarYear; _y < LunarData.MAX_YEAR; _y++) {
|
||||||
|
final short[] a = LunarCodes.monthCodes(_y);
|
||||||
|
int lunarMonths = a.length - 1;
|
||||||
|
sum -= lunarMonths;
|
||||||
|
if (sum > 0) {
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
if (sum <= 0) {
|
||||||
|
if (sum == 0) m = lunarMonths;
|
||||||
|
else m = lunarMonths + sum;
|
||||||
|
isLeapMonth = a[0] > 0 && a[0] + 1 == m;
|
||||||
|
if (isLeapMonth || a[0] > 0 && a[0] < m) {
|
||||||
|
m--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sum > 0) {
|
||||||
|
throw new IllegalArgumentException(String.format("add of month out of range: %d", amount));
|
||||||
|
}
|
||||||
|
} else if (amount < 0) {
|
||||||
|
if (sum > 0) {
|
||||||
|
m = sum;
|
||||||
|
} else if (sum == 0) {
|
||||||
|
Map.Entry<Integer, Boolean> en = LunarCodes.month(--y, -1);
|
||||||
|
m = en.getKey();
|
||||||
|
isLeapMonth = en.getValue();
|
||||||
|
} else {
|
||||||
|
for (int i = lunarYear - 1; i > LunarData.MINI_YEAR; i--) {
|
||||||
|
int lunarMonths = LunarCodes.monthCodes(i).length - 1;
|
||||||
|
sum += lunarMonths;
|
||||||
|
y--;
|
||||||
|
if (sum >= 0) {
|
||||||
|
Map.Entry<Integer, Boolean> en;
|
||||||
|
if (sum == 0) {
|
||||||
|
en = LunarCodes.month(--y, -1);
|
||||||
|
} else {
|
||||||
|
en = LunarCodes.month(y, sum + 1);
|
||||||
|
}
|
||||||
|
m = en.getKey();
|
||||||
|
isLeapMonth = en.getValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sum < 0) {
|
||||||
|
throw new IllegalArgumentException(String.format("add of month out of range: %d", amount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkComputeLunarDate(y, m, dayOfLunarMonth, isLeapMonth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验 day of month 是否是合法的,如果越限则从30号减到29号
|
||||||
|
*
|
||||||
|
* @param y lunar year
|
||||||
|
* @param m lunar month
|
||||||
|
* @param d lunar day of month
|
||||||
|
* @param isLeap 闰月
|
||||||
|
*/
|
||||||
|
private void checkComputeLunarDate(int y, int m, int d, boolean isLeap) {
|
||||||
|
int days = d;
|
||||||
|
if (d > 29 && d > LunarUtils.lengthOfMonth(y, m, isLeap)) {
|
||||||
|
days--;
|
||||||
|
}
|
||||||
|
computeByLunarDate(y, m, days, isLeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(int field, int value) {
|
||||||
|
super.set(field, value);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void roll(int field, int amount) {
|
||||||
|
super.roll(field, amount);
|
||||||
|
computeBySolarDate(get(Calendar.YEAR), get(Calendar.MONTH), get(Calendar.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (this.lunarYear < LunarData.MINI_YEAR || this.lunarYear > LunarData.MAX_YEAR || this.lunarMonth < 1
|
||||||
|
|| this.lunarMonth > 12 || this.dayOfLunarMonth < 1
|
||||||
|
|| this.dayOfLunarMonth > 30) {
|
||||||
|
return String.format("Wrong lunar date: %d %d %d", lunarYear, lunarMonth, dayOfLunarMonth);
|
||||||
|
}
|
||||||
|
return String.format("%s年%s%s月%s", LunarData.getYearName(this.lunarYear), this.isLeapMonth() ? "闰" : "",
|
||||||
|
LunarData.getMonthName(this.lunarMonth), LunarData.getDayName(this.dayOfLunarMonth));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof LunarCalendar)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
LunarCalendar that = (LunarCalendar) o;
|
||||||
|
return lunarYear == that.lunarYear &&
|
||||||
|
lunarMonth == that.lunarMonth &&
|
||||||
|
dayOfLunarMonth == that.dayOfLunarMonth &&
|
||||||
|
isLeapMonth == that.isLeapMonth &&
|
||||||
|
leapMonth == that.leapMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + lunarYear;
|
||||||
|
result = 31 * result + lunarMonth;
|
||||||
|
result = 31 * result + dayOfLunarMonth;
|
||||||
|
result = 31 * result + leapMonth;
|
||||||
|
result = 31 * result + (isLeapMonth ? 1 : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
LunarCalendar other = (LunarCalendar) super.clone();
|
||||||
|
other.lunarYear = getLunarYear();
|
||||||
|
other.lunarMonth = getLunarMonth();
|
||||||
|
other.dayOfLunarMonth = getDayOfLunarMonth();
|
||||||
|
other.leapMonth = getLeapMonth();
|
||||||
|
other.isLeapMonth = isLeapMonth();
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回农历日期,不包含年份
|
||||||
|
*
|
||||||
|
* @param showLeap 是否显示闰月的闰字
|
||||||
|
* @return 农历日期
|
||||||
|
*/
|
||||||
|
public String getLunar(boolean showLeap) {
|
||||||
|
if (this.lunarMonth < 1 || this.lunarMonth > 12 || this.dayOfLunarMonth < 1
|
||||||
|
|| this.dayOfLunarMonth > 30) {
|
||||||
|
throw new IllegalArgumentException(String.format("Wrong lunar dayOfLunarMonth: %d %d", lunarMonth, dayOfLunarMonth));
|
||||||
|
}
|
||||||
|
if (showLeap) {
|
||||||
|
return String.format("%s%s月%s", this.isLeapMonth() ? "闰" : "", LunarData.getMonthName(this.lunarMonth),
|
||||||
|
LunarData.getDayName(this.dayOfLunarMonth));
|
||||||
|
} else {
|
||||||
|
return String.format("%s月%s", LunarData.getMonthName(this.lunarMonth),
|
||||||
|
LunarData.getDayName(this.dayOfLunarMonth));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回中国农历的全名
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getFullLunarName() {
|
||||||
|
return String.format("%s %s %s", this, LunarData.getTraditionalYearName(this.lunarYear),
|
||||||
|
LunarData.getAnimalYearName(this.lunarYear));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建LunarInfo中某一年的一列公历日历编码<br>
|
||||||
|
* 公历日历编码:年份+月份+天,用于查询某个公历日期在某个LunarInfo列的哪一个区间<br>
|
||||||
|
*
|
||||||
|
* @param solarYear 年份
|
||||||
|
* @return 公历日历编码
|
||||||
|
*/
|
||||||
|
private int[] builderSolarCodes(int solarYear) {
|
||||||
|
if (solarYear < LunarData.MINI_YEAR || solarYear > LunarData.MAX_YEAR) {
|
||||||
|
throw new IllegalArgumentException("Illegal solar year: " + solarYear);
|
||||||
|
}
|
||||||
|
int lunarIndex = solarYear - LunarData.MINI_YEAR;
|
||||||
|
int[] solarCodes = new int[LunarData.LUNAR_INFO[lunarIndex].length];
|
||||||
|
for (int i = 0; i < solarCodes.length; i++) {
|
||||||
|
if (0 == i) { // 第一个数表示闰月,不用更改
|
||||||
|
solarCodes[i] = LunarData.LUNAR_INFO[lunarIndex][i];
|
||||||
|
} else if (1 == i) {
|
||||||
|
if (LunarData.LUNAR_INFO[lunarIndex][1] > 999) {
|
||||||
|
// 这年农历一月一日对应的公历实际是上一年的
|
||||||
|
solarCodes[i] = (solarYear - 1) * 10000 + LunarData.LUNAR_INFO[lunarIndex][i];
|
||||||
|
} else {
|
||||||
|
solarCodes[i] = solarYear * 10000 + LunarData.LUNAR_INFO[lunarIndex][i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
solarCodes[i] = solarYear * 10000 + LunarData.LUNAR_INFO[lunarIndex][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return solarCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过给定的农历日期,计算公历日期
|
||||||
|
*
|
||||||
|
* @param lunarYear 农历年
|
||||||
|
* @param lunarMonth 农历月,从1开始
|
||||||
|
* @param lunarDate 农历日期
|
||||||
|
* @param isLeapMonth 是否为闰月
|
||||||
|
*/
|
||||||
|
private void computeByLunarDate(final int lunarYear, final int lunarMonth, final int lunarDate,
|
||||||
|
final boolean isLeapMonth) {
|
||||||
|
if (lunarYear < LunarData.MINI_YEAR || lunarYear > LunarData.MAX_YEAR) {
|
||||||
|
throw new IllegalArgumentException(String.format("LunarYear must in (%d, %d)", LunarData.MINI_YEAR,
|
||||||
|
LunarData.MAX_YEAR));
|
||||||
|
}
|
||||||
|
this.lunarYear = lunarYear;
|
||||||
|
this.lunarMonth = lunarMonth;
|
||||||
|
this.dayOfLunarMonth = lunarDate;
|
||||||
|
this.isLeapMonth = isLeapMonth;
|
||||||
|
short code = LunarCodes.lunarMonthCode(lunarYear, lunarMonth, isLeapMonth);
|
||||||
|
|
||||||
|
// 对设置的day of month 进行检查
|
||||||
|
if (lunarDate == 30) {
|
||||||
|
long length = LunarCodes.lengthOfMonth(lunarYear, lunarMonth, code);
|
||||||
|
if (length != 30) {
|
||||||
|
throw new IllegalArgumentException(String.format("农历%d年%d月, 闰月=%s,月天数为%d < %d", lunarYear,
|
||||||
|
lunarMonth, isLeapMonth, length, lunarDate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.set(Calendar.YEAR, lunarYear + LunarCodes.codeYear(code));
|
||||||
|
super.set(Calendar.MONTH, LunarCodes.codeMonth(code) - 1);
|
||||||
|
super.set(Calendar.DATE, LunarCodes.codeDay(code));
|
||||||
|
super.add(Calendar.DATE, lunarDate - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过给定公历日期,计算农历日期各个域值
|
||||||
|
* <br>
|
||||||
|
* 这个方法可能会被调用多次,后续看能否再做优化
|
||||||
|
* </br>
|
||||||
|
*
|
||||||
|
* @param solarYear 公历年
|
||||||
|
* @param solarMonth 公历月,0-11
|
||||||
|
* @param solarDate 公历日
|
||||||
|
*/
|
||||||
|
private void computeBySolarDate(final int solarYear, final int solarMonth, final int solarDate) {
|
||||||
|
if (solarYear < LunarData.MINI_YEAR
|
||||||
|
|| (solarYear == LunarData.MINI_YEAR && solarMonth < LunarData.MINI_MONTH)
|
||||||
|
|| (solarYear == LunarData.MINI_YEAR && solarMonth == LunarData.MINI_MONTH && solarDate < LunarData.MINI_DATE)
|
||||||
|
|| solarYear > LunarData.MAX_YEAR
|
||||||
|
|| (solarYear == LunarData.MAX_YEAR && solarMonth > LunarData.MAX_MONTH)
|
||||||
|
|| (solarYear == LunarData.MAX_YEAR && solarMonth == LunarData.MAX_MONTH && solarDate > LunarData.MAX_DATE)
|
||||||
|
) {
|
||||||
|
// 有些中间过程日期会超出可计算范围
|
||||||
|
// throw new IllegalArgumentException("Illegal solar year: " + solarYear);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int solarCode = solarYear * 10000 + 100 * (1 + solarMonth) + solarDate; // 公历码
|
||||||
|
leapMonth = LunarData.LUNAR_INFO[solarYear - LunarData.MINI_YEAR][0];
|
||||||
|
int[] solarCodes = builderSolarCodes(solarYear);
|
||||||
|
int newMonth = LunarUtils.binSearch(solarCodes, solarCode);
|
||||||
|
if (-1 == newMonth) {
|
||||||
|
throw new IllegalArgumentException("No lunarInfo found by solarCode: " + solarCode);
|
||||||
|
}
|
||||||
|
int xDate = Long.valueOf(LunarCodes.solarDateCodesDiff(solarCode, solarCodes[newMonth], Calendar.DATE)).intValue();
|
||||||
|
if (0 == newMonth) {// 在上一年
|
||||||
|
int preYear = solarYear - 1;
|
||||||
|
leapMonth = LunarData.LUNAR_INFO[preYear - LunarData.MINI_YEAR][0];
|
||||||
|
short[] preSolarCodes = LunarData.LUNAR_INFO[preYear - LunarData.MINI_YEAR];
|
||||||
|
// 取上年农历12月1号公历日期码
|
||||||
|
int nearSolarCode = preSolarCodes[preSolarCodes.length - 1]; // 上一年12月1号
|
||||||
|
// 下一年公历1月表示为了13月,这里做翻译,并计算出日期码
|
||||||
|
nearSolarCode = (nearSolarCode / 100 == 13 ? preYear + 1 : preYear) * 10000
|
||||||
|
+ (nearSolarCode / 100 == 13 ? nearSolarCode - 1200 : nearSolarCode);
|
||||||
|
if (nearSolarCode > solarCode) {// 此公历日期在上一年农历12月1号,之前,即在上年农历11月内
|
||||||
|
newMonth = 11;
|
||||||
|
// 取农历11月的公历码
|
||||||
|
nearSolarCode = preYear * 10000 + preSolarCodes[preSolarCodes.length - 2];
|
||||||
|
} else {// 此公历日期在上一年农历12月内
|
||||||
|
newMonth = 12;
|
||||||
|
}
|
||||||
|
xDate = Long.valueOf(LunarCodes.solarDateCodesDiff(solarCode, nearSolarCode, Calendar.DATE)).intValue();
|
||||||
|
if (xDate < 0) {
|
||||||
|
throw new IllegalArgumentException("Wrong solarCode: " + solarCode);
|
||||||
|
}
|
||||||
|
this.dayOfLunarMonth = 1 + xDate;
|
||||||
|
this.lunarYear = preYear;
|
||||||
|
this.lunarMonth = newMonth;
|
||||||
|
this.isLeapMonth = 0 != leapMonth && (leapMonth == newMonth);
|
||||||
|
} else if (solarCodes.length == newMonth + 1 && xDate >= 30) {// 在下一年(公历12月只有30天)
|
||||||
|
newMonth = 1; // 农历肯定是1月
|
||||||
|
// 取下一年的公历日期码
|
||||||
|
short[] nextSolarCodes = LunarData.LUNAR_INFO[solarYear + 1 - LunarData.MINI_YEAR];
|
||||||
|
// 取下一年农历1月1号公历日期码
|
||||||
|
int nearSolarCode = solarYear * 10000 + nextSolarCodes[1]; // 下一年农历1月1号公历日期码
|
||||||
|
xDate = Long.valueOf(LunarCodes.solarDateCodesDiff(solarCode, nearSolarCode, Calendar.DATE)).intValue();
|
||||||
|
if (xDate < 0) {
|
||||||
|
throw new IllegalArgumentException("Wrong solarCode: " + solarCode);
|
||||||
|
}
|
||||||
|
this.dayOfLunarMonth = 1 + xDate;
|
||||||
|
this.lunarYear = solarYear + 1; // 农历年到了下一年
|
||||||
|
this.lunarMonth = newMonth;
|
||||||
|
this.isLeapMonth = false; // 农历1月不可能为闰月
|
||||||
|
} else {
|
||||||
|
if (xDate < 0) {
|
||||||
|
throw new IllegalArgumentException("Wrong solarCode: " + solarCode);
|
||||||
|
}
|
||||||
|
this.dayOfLunarMonth = 1 + xDate;
|
||||||
|
this.lunarYear = solarYear;
|
||||||
|
this.isLeapMonth = 0 != leapMonth && (leapMonth + 1 == newMonth);
|
||||||
|
if (0 != leapMonth && leapMonth < newMonth) {
|
||||||
|
this.lunarMonth = newMonth - 1;
|
||||||
|
} else {
|
||||||
|
this.lunarMonth = newMonth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------ getter and setter --------------------------------
|
||||||
|
|
||||||
|
public int getLunarYear() {
|
||||||
|
return lunarYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLunarMonth() {
|
||||||
|
return lunarMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDayOfLunarMonth() {
|
||||||
|
return dayOfLunarMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLeapMonth() {
|
||||||
|
return leapMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLeapMonth() {
|
||||||
|
return isLeapMonth;
|
||||||
|
}
|
||||||
|
}
|
||||||
157
src/main/java/com/github/heqiao2010/lunar/LunarCodes.java
Normal file
157
src/main/java/com/github/heqiao2010/lunar/LunarCodes.java
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
package com.github.heqiao2010.lunar;
|
||||||
|
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.github.heqiao2010.lunar.LunarData.LUNAR_INFO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历/公历对照代码工具方法集合
|
||||||
|
*/
|
||||||
|
public class LunarCodes {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历年的代码数组
|
||||||
|
* @param year 农历年
|
||||||
|
* @return 代码数组
|
||||||
|
*/
|
||||||
|
public static short[] monthCodes(int year) {
|
||||||
|
return LUNAR_INFO[year - LunarData.MINI_YEAR];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从代码中获取年份,大于12时表示下一年
|
||||||
|
* @param code 代码
|
||||||
|
* @return 0/1 今年或者下一年
|
||||||
|
*/
|
||||||
|
public static int codeYear(int code) {
|
||||||
|
return code / 100 > 12 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从代码中获取农历月初一在公历中的月份
|
||||||
|
* @param code 代码
|
||||||
|
* @return 公历月份
|
||||||
|
*/
|
||||||
|
public static int codeMonth(int code) {
|
||||||
|
int m = code / 100;
|
||||||
|
if (m > 12) m -= 12;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从代码中获取农历日在公历中的日 (day of month)
|
||||||
|
* @param code 代码
|
||||||
|
* @return 公历日
|
||||||
|
*/
|
||||||
|
public static int codeDay(int code) {
|
||||||
|
return code % 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 求一个农历月的天数
|
||||||
|
* @param lunarYear 农历年
|
||||||
|
* @param month 农历月
|
||||||
|
* @param code 农历月有日期,Mdd 表示
|
||||||
|
* @return 月的天数
|
||||||
|
*/
|
||||||
|
public static long lengthOfMonth(int lunarYear, int month, short code) {
|
||||||
|
short md2;
|
||||||
|
short[] starts = monthCodes(lunarYear);
|
||||||
|
int y2 = lunarYear;
|
||||||
|
if (month + 1 < starts.length && starts[month] == code) {
|
||||||
|
md2 = starts[month + 1];
|
||||||
|
} else if (month + 2 < starts.length && starts[month + 1] == code) {
|
||||||
|
md2 = starts[month + 2];
|
||||||
|
} else if (lunarYear - LunarData.MINI_YEAR + 1 < LUNAR_INFO.length) {
|
||||||
|
md2 = monthCodes(lunarYear + 1)[1];
|
||||||
|
y2 ++;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("lunar date out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
int y1 = lunarYear + codeYear(code);
|
||||||
|
int m1 = codeMonth(code);
|
||||||
|
int d1 = codeDay(code);
|
||||||
|
|
||||||
|
y2 += codeYear(md2);
|
||||||
|
int m2 = codeMonth(md2);
|
||||||
|
int d2 = codeDay(md2);
|
||||||
|
|
||||||
|
Calendar c1 = Calendar.getInstance();
|
||||||
|
c1.set(y1, m1 - 1, d1);
|
||||||
|
Calendar c2 = Calendar.getInstance();
|
||||||
|
c2.set(y2, m2 - 1, d2);
|
||||||
|
|
||||||
|
return LunarUtils.solarDiff(c2, c1, Calendar.DATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据农历年和 LUNAR_INFO 中的下标来确定月份和闰月
|
||||||
|
*
|
||||||
|
* @param year 农历年
|
||||||
|
* @param index LUNAR_INFO 月份数组中的下标
|
||||||
|
* @return 月, 闰月
|
||||||
|
*/
|
||||||
|
public static Map.Entry<Integer, Boolean> month(int year, int index) {
|
||||||
|
short[] a = monthCodes(year);
|
||||||
|
int i = index;
|
||||||
|
if (index == -1) {
|
||||||
|
i = a.length - 1;
|
||||||
|
}
|
||||||
|
boolean isLeap = a[0] > 0 && a[0] + 1 == i;
|
||||||
|
int month = isLeap || a[0] > 0 && a[0] < i ? i - 1 : i;
|
||||||
|
return new AbstractMap.SimpleImmutableEntry(month, isLeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算月份 Mdd 代码在数组中的位置
|
||||||
|
*
|
||||||
|
* @param year 农历年
|
||||||
|
* @param month 农历月
|
||||||
|
* @param isLeapMonth 闰月
|
||||||
|
* @return 月所在的下标
|
||||||
|
*/
|
||||||
|
public static int monthIndex(int year, int month, boolean isLeapMonth) {
|
||||||
|
short[] a = monthCodes(year);
|
||||||
|
if (a[0] > 0 && a[0] < month || a[0] == month && isLeapMonth) {
|
||||||
|
return month + 1;
|
||||||
|
}
|
||||||
|
return month;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断两个整数所代表公历日期的差值<br>
|
||||||
|
* 一年按365天计算,一个月按30天计算<br>
|
||||||
|
*
|
||||||
|
* @param solarCode1 农历日期代码
|
||||||
|
* @param solarCode2 农历日期代码
|
||||||
|
* @param field 差值单位
|
||||||
|
* @return 差值
|
||||||
|
*/
|
||||||
|
public static long solarDateCodesDiff(int solarCode1, int solarCode2, int field) {
|
||||||
|
GregorianCalendar c1 = new GregorianCalendar(solarCode1 / 10000, solarCode1 % 10000 / 100 - 1,
|
||||||
|
solarCode1 % 10000 % 100);
|
||||||
|
GregorianCalendar c2 = new GregorianCalendar(solarCode2 / 10000, solarCode2 % 10000 / 100 - 1,
|
||||||
|
solarCode2 % 10000 % 100);
|
||||||
|
return LunarUtils.solarDiff(c1, c2, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历月的代码
|
||||||
|
* @param lunarYear 农历月
|
||||||
|
* @param lunarMonth 农历月
|
||||||
|
* @param isLeapMonth 闰月
|
||||||
|
* @return 代码
|
||||||
|
*/
|
||||||
|
public static short lunarMonthCode(int lunarYear, int lunarMonth, boolean isLeapMonth) {
|
||||||
|
short[] codes = monthCodes(lunarYear);
|
||||||
|
int index = lunarMonth;
|
||||||
|
if (codes[0] > 0 && codes[0] < lunarMonth || codes[0] == lunarMonth && isLeapMonth) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return codes[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
423
src/main/java/com/github/heqiao2010/lunar/LunarData.java
Normal file
423
src/main/java/com/github/heqiao2010/lunar/LunarData.java
Normal file
@@ -0,0 +1,423 @@
|
|||||||
|
package com.github.heqiao2010.lunar;
|
||||||
|
|
||||||
|
public class LunarData {
|
||||||
|
/**
|
||||||
|
* 支持的最小日期1850-02-12
|
||||||
|
*/
|
||||||
|
public final static int MINI_YEAR = 1850;
|
||||||
|
public final static int MINI_MONTH = 1;
|
||||||
|
public final static int MINI_DATE = 12;
|
||||||
|
/**
|
||||||
|
* 支持的最大日期2150-12-31
|
||||||
|
*/
|
||||||
|
public final static int MAX_YEAR = 2150;
|
||||||
|
public final static int MAX_MONTH = 11;
|
||||||
|
public final static int MAX_DATE = 31;
|
||||||
|
/**
|
||||||
|
* 10天干
|
||||||
|
* '甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'
|
||||||
|
*/
|
||||||
|
static final char[] LunarGan = {'\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a',
|
||||||
|
'\u8f9b', '\u58ec', '\u7678'};
|
||||||
|
/**
|
||||||
|
* 12地支
|
||||||
|
* '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'
|
||||||
|
*/
|
||||||
|
static final char[] LunarZhi = {'\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348',
|
||||||
|
'\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'};
|
||||||
|
/**
|
||||||
|
* 12生肖
|
||||||
|
* '鼠', '牛', '虎', '兔', '龍', '蛇', '馬', '羊', '猴', '雞', '犬', '豬'
|
||||||
|
*/
|
||||||
|
static final char[] LunarAnimalName = {'\u9f20', '\u725b', '\u864e', '\u5154', '\u9f8d', '\u86c7',
|
||||||
|
'\u99ac', '\u7f8a', '\u7334', '\u96de', '\u72ac', '\u8c6c'};
|
||||||
|
/**
|
||||||
|
* 农历年份名
|
||||||
|
* '〇', '一', '二', '三', '四', '五', '六', '七', '八', '九'
|
||||||
|
*/
|
||||||
|
static final char[] LunarYearName = {'\u3007', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94',
|
||||||
|
'\u516d', '\u4e03', '\u516b', '\u4e5d'};
|
||||||
|
/**
|
||||||
|
* 农历月份名
|
||||||
|
* '正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '冬', '腊'
|
||||||
|
*/
|
||||||
|
static final char[] LunarMonthName = {'\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d',
|
||||||
|
'\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'};
|
||||||
|
/**
|
||||||
|
* 农历日期名
|
||||||
|
* "初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九",
|
||||||
|
* "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二",
|
||||||
|
* "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"
|
||||||
|
*/
|
||||||
|
static final String[] LunarDayName = {"\u521d\u4e00", "\u521d\u4e8c", "\u521d\u4e09", "\u521d\u56db",
|
||||||
|
"\u521d\u4e94", "\u521d\u516d", "\u521d\u4e03", "\u521d\u516b", "\u521d\u4e5d", "\u521d\u5341",
|
||||||
|
"\u5341\u4e00", "\u5341\u4e8c", "\u5341\u4e09", "\u5341\u56db", "\u5341\u4e94", "\u5341\u516d",
|
||||||
|
"\u5341\u4e03", "\u5341\u516b", "\u5341\u4e5d", "\u4e8c\u5341", "\u5eff\u4e00", "\u5eff\u4e8c",
|
||||||
|
"\u5eff\u4e09", "\u5eff\u56db", "\u5eff\u4e94", "\u5eff\u516d", "\u5eff\u4e03", "\u5eff\u516b",
|
||||||
|
"\u5eff\u4e5d", "\u4e09\u5341"};
|
||||||
|
/**
|
||||||
|
* 农历信息.<br>
|
||||||
|
* 每个数组的第一个数表示该年闰月月份,为0表示不闰月<br>
|
||||||
|
* 数组中其他数表示该月初一对应的公历日期<br>
|
||||||
|
*/
|
||||||
|
final static short[][] LUNAR_INFO = {
|
||||||
|
{0, 212, 314, 412, 512, 610, 709, 808, 906, 1005, 1104, 1204, 1302}, // 1850
|
||||||
|
{8, 201, 303, 402, 501, 531, 629, 728, 827, 925, 1024, 1123, 1222, 1321}, // 1851
|
||||||
|
{0, 220, 321, 331, 419, 519, 618, 717, 815, 914, 1013, 1112, 1211, 1309}, // 1852
|
||||||
|
{0, 208, 310, 408, 508, 607, 706, 805, 903, 1003, 1101, 1201, 1230}, // 1853
|
||||||
|
{7, 129, 227, 329, 427, 527, 625, 725, 824, 922, 1022, 1120, 1220, 1318}, // 1854
|
||||||
|
{0, 217, 318, 416, 516, 614, 714, 813, 911, 1011, 1110, 1209, 1308}, // 1855
|
||||||
|
{0, 206, 307, 405, 504, 603, 702, 801, 830, 929, 1029, 1128, 1227}, // 1856
|
||||||
|
{5, 126, 224, 326, 424, 523, 622, 721, 820, 918, 1018, 1116, 1216, 1315}, // 1857
|
||||||
|
{0, 214, 315, 414, 513, 611, 711, 809, 907, 1007, 1106, 1205, 1304}, // 1858
|
||||||
|
{0, 203, 305, 403, 503, 601, 630, 730, 828, 926, 1026, 1124, 1224}, // 1859
|
||||||
|
{3, 123, 222, 322, 421, 521, 619, 718, 817, 915, 1014, 1113, 1212, 1311}, // 1860
|
||||||
|
{0, 210, 311, 410, 510, 608, 708, 806, 905, 1004, 1103, 1202, 1231}, // 1861
|
||||||
|
{8, 130, 301, 330, 429, 528, 627, 727, 825, 924, 1023, 1122, 1221, 1319}, // 1862
|
||||||
|
{0, 218, 319, 418, 518, 616, 716, 814, 913, 1013, 1111, 1211, 1309}, // 1863
|
||||||
|
{0, 208, 308, 406, 506, 604, 704, 802, 901, 1001, 1030, 1129, 1229, 1327}, // 1864
|
||||||
|
{6, 127, 226, 327, 425, 525, 623, 723, 821, 920, 1020, 1118, 1218, 1317}, // 1865
|
||||||
|
{0, 215, 317, 415, 514, 613, 712, 810, 909, 1009, 1107, 1207, 1306}, // 1866
|
||||||
|
{0, 205, 306, 405, 504, 602, 702, 731, 829, 928, 1027, 1126, 1226}, // 1867
|
||||||
|
{4, 125, 223, 324, 423, 522, 620, 720, 818, 916, 1016, 1114, 1214, 1313}, // 1868
|
||||||
|
{0, 211, 313, 412, 512, 610, 709, 808, 906, 1005, 1104, 1203, 1302}, // 1869
|
||||||
|
{10, 131, 302, 401, 501, 530, 629, 728, 827, 925, 1024, 1123, 1222, 1321}, // 1870
|
||||||
|
{0, 219, 321, 420, 519, 618, 718, 816, 915, 1014, 1113, 1212, 1310}, // 1871
|
||||||
|
{0, 209, 309, 408, 507, 606, 706, 804, 903, 1002, 1101, 1201, 1230}, // 1872
|
||||||
|
{6, 129, 227, 328, 427, 526, 625, 724, 823, 922, 1021, 1120, 1220, 1318}, // 1873
|
||||||
|
{0, 217, 318, 416, 516, 614, 714, 812, 911, 1010, 1109, 1209, 1308}, // 1874
|
||||||
|
{0, 206, 308, 406, 505, 604, 703, 801, 831, 929, 1029, 1128, 1228}, // 1875
|
||||||
|
{5, 126, 225, 326, 424, 523, 622, 721, 819, 918, 1017, 1116, 1216, 1314}, // 1876
|
||||||
|
{0, 213, 315, 414, 513, 611, 711, 809, 907, 1007, 1105, 1205, 1303}, // 1877
|
||||||
|
{0, 202, 304, 403, 502, 601, 630, 730, 828, 926, 1026, 1124, 1224}, // 1878
|
||||||
|
{3, 122, 221, 323, 421, 521, 620, 719, 818, 916, 1015, 1114, 1213, 1312}, // 1879
|
||||||
|
{0, 210, 311, 409, 509, 608, 707, 806, 905, 1004, 1103, 1202, 1231}, // 1880
|
||||||
|
{7, 130, 228, 330, 428, 528, 626, 726, 825, 923, 1023, 1122, 1221, 1320}, // 1881
|
||||||
|
{0, 218, 319, 418, 517, 616, 715, 814, 912, 1012, 1111, 1210, 1309}, // 1882
|
||||||
|
{0, 208, 309, 407, 507, 605, 704, 803, 901, 1001, 1031, 1130, 1229}, // 1883
|
||||||
|
{5, 128, 227, 327, 425, 525, 623, 722, 821, 919, 1019, 1118, 1217, 1316}, // 1884
|
||||||
|
{0, 215, 317, 415, 514, 613, 712, 810, 909, 1008, 1107, 1206, 1305}, // 1885
|
||||||
|
{0, 204, 306, 404, 504, 602, 702, 731, 829, 928, 1027, 1126, 1225}, // 1886
|
||||||
|
{4, 124, 223, 325, 423, 523, 621, 721, 819, 917, 1017, 1115, 1215, 1313}, // 1887
|
||||||
|
{0, 212, 313, 411, 511, 610, 709, 808, 906, 1005, 1104, 1203, 1302}, // 1888
|
||||||
|
{12, 131, 302, 331, 430, 530, 628, 728, 826, 925, 1024, 1123, 1222, 1321}, // 1889
|
||||||
|
{0, 219, 321, 419, 519, 617, 717, 816, 914, 1014, 1112, 1212, 1310}, // 1890
|
||||||
|
{0, 209, 310, 409, 508, 607, 706, 805, 903, 1003, 1102, 1201, 1231}, // 1891
|
||||||
|
{6, 130, 228, 328, 427, 526, 624, 724, 822, 921, 1021, 1119, 1219, 1318}, // 1892
|
||||||
|
{0, 217, 318, 416, 516, 614, 713, 812, 910, 1010, 1108, 1208, 1307}, // 1893
|
||||||
|
{0, 206, 307, 406, 505, 604, 703, 801, 831, 929, 1029, 1127, 1227}, // 1894
|
||||||
|
{5, 126, 225, 326, 425, 524, 623, 722, 820, 919, 1018, 1117, 1216, 1315}, // 1895
|
||||||
|
{0, 214, 314, 413, 513, 611, 711, 809, 907, 1007, 1105, 1205, 1303}, // 1896
|
||||||
|
{0, 202, 303, 402, 502, 531, 630, 730, 828, 926, 1026, 1124, 1224}, // 1897
|
||||||
|
{3, 122, 221, 322, 421, 520, 619, 719, 817, 916, 1015, 1114, 1213, 1312}, // 1898
|
||||||
|
{0, 210, 312, 410, 510, 608, 708, 806, 905, 1005, 1103, 1203, 1301}, // 1899
|
||||||
|
{8, 131, 301, 331, 429, 528, 627, 726, 825, 924, 1023, 1122, 1222, 1320}, // 1900
|
||||||
|
{0, 219, 320, 419, 518, 616, 716, 814, 913, 1012, 1111, 1211, 1310}, // 1901
|
||||||
|
{0, 208, 310, 408, 508, 606, 705, 804, 902, 1002, 1031, 1130, 1230}, // 1902
|
||||||
|
{5, 129, 227, 329, 427, 527, 625, 724, 823, 921, 1020, 1119, 1219, 1317}, // 1903
|
||||||
|
{0, 216, 317, 416, 515, 614, 713, 811, 910, 1009, 1107, 1207, 1306}, // 1904
|
||||||
|
{0, 204, 306, 405, 504, 603, 703, 801, 830, 929, 1028, 1127, 1226}, // 1905
|
||||||
|
{4, 125, 223, 325, 424, 523, 622, 721, 820, 918, 1018, 1116, 1216, 1314}, // 1906
|
||||||
|
{0, 213, 314, 413, 512, 611, 710, 809, 908, 1007, 1106, 1205, 1304}, // 1907
|
||||||
|
{0, 202, 303, 401, 430, 530, 629, 728, 827, 925, 1025, 1124, 1223}, // 1908
|
||||||
|
{2, 122, 220, 322, 420, 519, 618, 717, 816, 914, 1014, 1113, 1213, 1311}, // 1909
|
||||||
|
{0, 210, 311, 410, 509, 607, 707, 805, 904, 1003, 1102, 1202, 1301}, // 1910
|
||||||
|
{6, 130, 301, 330, 429, 528, 626, 726, 824, 922, 1022, 1121, 1220, 1319}, // 1911
|
||||||
|
{0, 218, 319, 417, 517, 615, 714, 813, 911, 1010, 1109, 1209, 1307}, // 1912
|
||||||
|
{0, 206, 308, 407, 506, 605, 704, 802, 901, 930, 1029, 1128, 1227}, // 1913
|
||||||
|
{5, 126, 225, 327, 425, 525, 623, 723, 821, 920, 1019, 1117, 1217, 1315}, // 1914
|
||||||
|
{0, 214, 316, 414, 514, 613, 712, 811, 909, 1009, 1107, 1207, 1305}, // 1915
|
||||||
|
{0, 203, 304, 403, 502, 601, 630, 730, 829, 927, 1027, 1125, 1225}, // 1916
|
||||||
|
{2, 123, 222, 323, 421, 521, 619, 719, 818, 916, 1016, 1115, 1214, 1313}, // 1917
|
||||||
|
{0, 211, 313, 411, 510, 609, 708, 807, 905, 1005, 1104, 1203, 1302}, // 1918
|
||||||
|
{7, 201, 302, 401, 430, 529, 628, 727, 825, 924, 1024, 1122, 1222, 1321}, // 1919
|
||||||
|
{0, 220, 320, 419, 518, 616, 716, 814, 912, 1012, 1110, 1210, 1309}, // 1920
|
||||||
|
{0, 208, 310, 408, 508, 606, 705, 804, 902, 1001, 1031, 1129, 1229}, // 1921
|
||||||
|
{5, 128, 227, 328, 427, 527, 625, 724, 823, 921, 1020, 1119, 1218, 1317}, // 1922
|
||||||
|
{0, 216, 317, 416, 516, 614, 714, 812, 911, 1010, 1108, 1208, 1306}, // 1923
|
||||||
|
{0, 205, 305, 404, 504, 602, 702, 801, 830, 929, 1028, 1127, 1226}, // 1924
|
||||||
|
{4, 124, 223, 324, 423, 522, 621, 721, 819, 918, 1018, 1116, 1216, 1314}, // 1925
|
||||||
|
{0, 213, 314, 412, 512, 610, 710, 808, 907, 1007, 1105, 1205, 1304}, // 1926
|
||||||
|
{0, 202, 304, 402, 501, 531, 629, 729, 827, 926, 1025, 1124, 1224}, // 1927
|
||||||
|
{2, 123, 221, 322, 420, 519, 618, 717, 815, 914, 1013, 1112, 1212, 1311}, // 1928
|
||||||
|
{0, 210, 311, 410, 509, 607, 707, 805, 903, 1003, 1101, 1201, 1231}, // 1929
|
||||||
|
{6, 130, 228, 330, 429, 528, 626, 726, 824, 922, 1022, 1120, 1220, 1319}, // 1930
|
||||||
|
{0, 217, 319, 418, 517, 616, 715, 814, 912, 1011, 1110, 1209, 1308}, // 1931
|
||||||
|
{0, 206, 307, 406, 506, 604, 704, 802, 901, 930, 1029, 1128, 1227}, // 1932
|
||||||
|
{5, 126, 224, 326, 425, 524, 623, 723, 821, 920, 1019, 1118, 1217, 1315}, // 1933
|
||||||
|
{0, 214, 315, 414, 513, 612, 712, 810, 909, 1008, 1107, 1207, 1305}, // 1934
|
||||||
|
{0, 204, 305, 403, 503, 601, 701, 730, 829, 928, 1027, 1126, 1226}, // 1935
|
||||||
|
{3, 124, 223, 323, 421, 521, 619, 718, 817, 916, 1015, 1114, 1214, 1313}, // 1936
|
||||||
|
{0, 211, 313, 411, 510, 609, 708, 806, 905, 1004, 1103, 1203, 1302}, // 1937
|
||||||
|
{7, 131, 302, 401, 430, 529, 628, 727, 825, 924, 1023, 1122, 1222, 1320}, // 1938
|
||||||
|
{0, 219, 321, 420, 519, 617, 717, 815, 913, 1013, 1111, 1211, 1309}, // 1939
|
||||||
|
{0, 208, 309, 408, 507, 606, 705, 804, 902, 1001, 1031, 1129, 1229}, // 1940
|
||||||
|
{6, 127, 226, 328, 426, 526, 625, 724, 823, 921, 1020, 1119, 1218, 1317}, // 1941
|
||||||
|
{0, 215, 317, 415, 515, 614, 713, 812, 910, 1010, 1108, 1208, 1306}, // 1942
|
||||||
|
{0, 205, 306, 405, 504, 603, 702, 801, 831, 929, 1029, 1127, 1227}, // 1943
|
||||||
|
{4, 125, 224, 324, 423, 522, 621, 720, 819, 917, 1017, 1116, 1215, 1314}, // 1944
|
||||||
|
{0, 213, 314, 412, 512, 610, 709, 808, 906, 1006, 1105, 1205, 1303}, // 1945
|
||||||
|
{0, 202, 304, 402, 501, 531, 629, 728, 827, 925, 1025, 1124, 1223}, // 1946
|
||||||
|
{2, 122, 221, 323, 421, 520, 619, 718, 816, 915, 1014, 1113, 1212, 1311}, // 1947
|
||||||
|
{0, 210, 311, 409, 509, 607, 707, 805, 903, 1003, 1101, 1201, 1230}, // 1948
|
||||||
|
{7, 129, 228, 329, 428, 528, 626, 726, 824, 922, 1022, 1120, 1220, 1318}, // 1949
|
||||||
|
{0, 217, 318, 417, 517, 615, 715, 814, 912, 1011, 1110, 1209, 1308}, // 1950
|
||||||
|
{0, 206, 308, 406, 506, 605, 704, 803, 901, 1001, 1030, 1129, 1228}, // 1951
|
||||||
|
{5, 127, 225, 326, 424, 524, 622, 722, 820, 919, 1019, 1117, 1217, 1315}, // 1952
|
||||||
|
{0, 214, 315, 414, 513, 611, 711, 810, 908, 1008, 1107, 1206, 1305}, // 1953
|
||||||
|
{0, 203, 305, 403, 503, 601, 630, 730, 828, 927, 1027, 1125, 1225}, // 1954
|
||||||
|
{3, 124, 222, 324, 422, 522, 620, 719, 818, 916, 1016, 1114, 1214, 1313}, // 1955
|
||||||
|
{0, 212, 312, 411, 510, 609, 708, 806, 905, 1004, 1103, 1202, 1301}, // 1956
|
||||||
|
{8, 131, 302, 331, 430, 529, 628, 727, 825, 924, 1023, 1122, 1221, 1320}, // 1957
|
||||||
|
{0, 218, 320, 419, 519, 617, 717, 815, 913, 1013, 1111, 1211, 1309}, // 1958
|
||||||
|
{0, 208, 309, 408, 508, 606, 706, 804, 903, 1002, 1101, 1130, 1230}, // 1959
|
||||||
|
{6, 128, 227, 327, 426, 525, 624, 724, 822, 921, 1020, 1119, 1218, 1317}, // 1960
|
||||||
|
{0, 215, 317, 415, 515, 613, 713, 811, 910, 1010, 1108, 1208, 1306}, // 1961
|
||||||
|
{0, 205, 306, 405, 504, 602, 702, 731, 830, 929, 1028, 1127, 1227}, // 1962
|
||||||
|
{4, 125, 224, 325, 424, 523, 621, 721, 819, 918, 1017, 1116, 1216, 1315}, // 1963
|
||||||
|
{0, 213, 314, 412, 512, 610, 709, 808, 906, 1006, 1104, 1204, 1303}, // 1964
|
||||||
|
{0, 202, 303, 402, 501, 531, 629, 728, 827, 925, 1024, 1123, 1223}, // 1965
|
||||||
|
{3, 121, 220, 322, 421, 520, 619, 718, 816, 915, 1014, 1112, 1212, 1311}, // 1966
|
||||||
|
{0, 209, 311, 410, 509, 608, 708, 806, 904, 1004, 1102, 1202, 1231}, // 1967
|
||||||
|
{7, 130, 228, 329, 427, 527, 626, 725, 824, 922, 1022, 1120, 1220, 1318}, // 1968
|
||||||
|
{0, 217, 318, 417, 516, 615, 714, 813, 912, 1011, 1110, 1209, 1308}, // 1969
|
||||||
|
{0, 206, 308, 406, 505, 604, 703, 802, 901, 930, 1030, 1129, 1228}, // 1970
|
||||||
|
{5, 127, 225, 327, 425, 524, 623, 722, 821, 919, 1019, 1118, 1218, 1316}, // 1971
|
||||||
|
{0, 215, 315, 414, 513, 611, 711, 809, 908, 1007, 1106, 1206, 1304}, // 1972
|
||||||
|
{0, 203, 305, 403, 503, 601, 630, 730, 828, 926, 1026, 1125, 1224}, // 1973
|
||||||
|
{4, 123, 222, 324, 422, 522, 620, 719, 818, 916, 1015, 1114, 1214, 1312}, // 1974
|
||||||
|
{0, 211, 313, 412, 511, 610, 709, 807, 906, 1005, 1103, 1203, 1301}, // 1975
|
||||||
|
{8, 131, 301, 331, 429, 529, 627, 727, 825, 924, 1023, 1121, 1221, 1319}, // 1976
|
||||||
|
{0, 218, 320, 418, 518, 617, 716, 815, 913, 1013, 1111, 1211, 1309}, // 1977
|
||||||
|
{0, 207, 309, 407, 507, 606, 705, 804, 903, 1002, 1101, 1130, 1230}, // 1978
|
||||||
|
{6, 128, 227, 328, 426, 526, 624, 724, 823, 921, 1021, 1120, 1219, 1318}, // 1979
|
||||||
|
{0, 216, 317, 415, 514, 613, 712, 811, 909, 1009, 1108, 1207, 1306}, // 1980
|
||||||
|
{0, 205, 306, 405, 504, 602, 702, 731, 829, 928, 1028, 1126, 1226}, // 1981
|
||||||
|
{4, 125, 224, 325, 424, 523, 621, 721, 819, 917, 1017, 1115, 1215, 1314}, // 1982
|
||||||
|
{0, 213, 315, 413, 513, 611, 710, 809, 907, 1006, 1105, 1204, 1303}, // 1983
|
||||||
|
{10, 202, 303, 401, 501, 531, 629, 728, 827, 925, 1024, 1123, 1222, 1321}, // 1984
|
||||||
|
{0, 220, 321, 420, 520, 618, 718, 816, 915, 1014, 1112, 1212, 1310}, // 1985
|
||||||
|
{0, 209, 310, 409, 509, 607, 707, 806, 904, 1004, 1102, 1202, 1231}, // 1986
|
||||||
|
{6, 129, 228, 329, 428, 527, 626, 726, 824, 923, 1023, 1121, 1221, 1319}, // 1987
|
||||||
|
{0, 217, 318, 416, 516, 614, 714, 812, 911, 1011, 1109, 1209, 1308}, // 1988
|
||||||
|
{0, 206, 308, 406, 505, 604, 703, 802, 831, 930, 1029, 1128, 1228}, // 1989
|
||||||
|
{5, 127, 225, 327, 425, 524, 623, 722, 820, 919, 1018, 1117, 1217, 1316}, // 1990
|
||||||
|
{0, 215, 316, 415, 514, 612, 712, 810, 908, 1008, 1106, 1206, 1305}, // 1991
|
||||||
|
{0, 204, 304, 403, 503, 601, 630, 730, 828, 926, 1026, 1124, 1224}, // 1992
|
||||||
|
{3, 123, 221, 323, 422, 521, 620, 719, 818, 916, 1015, 1114, 1213, 1312}, // 1993
|
||||||
|
{0, 210, 312, 411, 511, 609, 709, 807, 906, 1005, 1103, 1203, 1301}, // 1994
|
||||||
|
{8, 131, 301, 331, 430, 529, 628, 727, 826, 925, 1024, 1122, 1222, 1320}, // 1995
|
||||||
|
{0, 219, 319, 418, 517, 616, 716, 814, 913, 1012, 1111, 1211, 1309}, // 1996
|
||||||
|
{0, 207, 309, 407, 507, 605, 705, 803, 902, 1002, 1031, 1130, 1230}, // 1997
|
||||||
|
{5, 128, 227, 328, 426, 526, 624, 723, 822, 921, 1020, 1119, 1219, 1317}, // 1998
|
||||||
|
{0, 216, 318, 416, 515, 614, 713, 811, 910, 1009, 1108, 1208, 1307}, // 1999
|
||||||
|
{0, 205, 306, 405, 504, 602, 702, 731, 829, 928, 1027, 1126, 1226}, // 2000
|
||||||
|
{4, 124, 223, 325, 423, 523, 621, 721, 819, 917, 1017, 1115, 1215, 1313}, // 2001
|
||||||
|
{0, 212, 314, 413, 512, 611, 710, 809, 907, 1006, 1105, 1204, 1303}, // 2002
|
||||||
|
{0, 201, 303, 402, 501, 531, 630, 729, 828, 926, 1025, 1124, 1223}, // 2003
|
||||||
|
{2, 122, 220, 321, 419, 519, 618, 717, 816, 914, 1014, 1112, 1212, 1310}, // 2004
|
||||||
|
{0, 209, 310, 409, 508, 607, 706, 805, 904, 1003, 1102, 1201, 1231}, // 2005
|
||||||
|
{7, 129, 228, 329, 428, 527, 626, 725, 824, 922, 1022, 1121, 1220, 1319}, // 2006
|
||||||
|
{0, 218, 319, 417, 517, 615, 714, 813, 911, 1011, 1110, 1210, 1308}, // 2007
|
||||||
|
{0, 207, 308, 406, 505, 604, 703, 801, 831, 929, 1029, 1128, 1227}, // 2008
|
||||||
|
{5, 126, 225, 327, 425, 524, 623, 722, 820, 919, 1018, 1117, 1216, 1315}, // 2009
|
||||||
|
{0, 214, 316, 414, 514, 612, 712, 810, 908, 1008, 1106, 1206, 1304}, // 2010
|
||||||
|
{0, 203, 305, 403, 503, 602, 701, 731, 829, 927, 1027, 1125, 1225}, // 2011
|
||||||
|
{4, 123, 222, 322, 421, 521, 619, 719, 817, 916, 1015, 1114, 1213, 1312}, // 2012
|
||||||
|
{0, 210, 312, 410, 510, 608, 708, 807, 905, 1005, 1103, 1203, 1301}, // 2013
|
||||||
|
{9, 131, 301, 331, 429, 529, 627, 727, 825, 924, 1024, 1122, 1222, 1320}, // 2014
|
||||||
|
{0, 219, 320, 419, 518, 616, 716, 814, 913, 1013, 1112, 1211, 1310}, // 2015
|
||||||
|
{0, 208, 309, 407, 507, 605, 704, 803, 901, 1001, 1031, 1129, 1229}, // 2016
|
||||||
|
{6, 128, 226, 328, 426, 526, 624, 723, 822, 920, 1020, 1118, 1218, 1317}, // 2017
|
||||||
|
{0, 216, 317, 416, 515, 614, 713, 811, 910, 1009, 1108, 1207, 1306}, // 2018
|
||||||
|
{0, 205, 307, 405, 505, 603, 703, 801, 830, 929, 1028, 1126, 1226}, // 2019
|
||||||
|
{4, 125, 223, 324, 423, 523, 621, 721, 819, 917, 1017, 1115, 1215, 1313}, // 2020
|
||||||
|
{0, 212, 313, 412, 512, 610, 710, 808, 907, 1006, 1105, 1204, 1303}, // 2021
|
||||||
|
{0, 201, 303, 401, 501, 530, 629, 729, 827, 926, 1025, 1124, 1223}, // 2022
|
||||||
|
{2, 122, 220, 322, 420, 519, 618, 718, 816, 915, 1015, 1113, 1213, 1311}, // 2023
|
||||||
|
{0, 210, 310, 409, 508, 606, 706, 804, 903, 1003, 1101, 1201, 1231}, // 2024
|
||||||
|
{6, 129, 228, 329, 428, 527, 625, 725, 823, 922, 1021, 1120, 1220, 1319}, // 2025
|
||||||
|
{0, 217, 319, 417, 517, 615, 714, 813, 911, 1010, 1109, 1209, 1308}, // 2026
|
||||||
|
{0, 206, 308, 407, 506, 605, 704, 802, 901, 930, 1029, 1128, 1228}, // 2027
|
||||||
|
{5, 126, 225, 326, 425, 524, 623, 722, 820, 919, 1018, 1116, 1216, 1315}, // 2028
|
||||||
|
{0, 213, 315, 414, 513, 612, 711, 810, 908, 1008, 1106, 1205, 1304}, // 2029
|
||||||
|
{0, 203, 304, 403, 502, 601, 701, 730, 829, 927, 1027, 1125, 1225}, // 2030
|
||||||
|
{3, 123, 221, 323, 422, 521, 620, 719, 818, 917, 1016, 1115, 1214, 1313}, // 2031
|
||||||
|
{0, 211, 312, 410, 509, 608, 707, 806, 905, 1004, 1103, 1203, 1301}, // 2032
|
||||||
|
{11, 131, 301, 331, 429, 528, 627, 726, 825, 923, 1023, 1122, 1222, 1320}, // 2033
|
||||||
|
{0, 219, 320, 419, 518, 616, 716, 814, 913, 1012, 1111, 1211, 1309}, // 2034
|
||||||
|
{0, 208, 310, 408, 508, 606, 705, 804, 902, 1001, 1031, 1130, 1229}, // 2035
|
||||||
|
{6, 128, 227, 328, 426, 526, 624, 723, 822, 920, 1019, 1118, 1217, 1316}, // 2036
|
||||||
|
{0, 215, 317, 416, 515, 614, 713, 811, 910, 1009, 1107, 1207, 1305}, // 2037
|
||||||
|
{0, 204, 306, 405, 504, 603, 702, 801, 830, 929, 1028, 1126, 1226}, // 2038
|
||||||
|
{5, 124, 223, 325, 423, 523, 622, 721, 820, 918, 1018, 1116, 1216, 1314}, // 2039
|
||||||
|
{0, 212, 313, 411, 511, 610, 709, 808, 906, 1006, 1105, 1204, 1303}, // 2040
|
||||||
|
{0, 201, 302, 401, 430, 530, 628, 728, 827, 925, 1025, 1124, 1223}, // 2041
|
||||||
|
{2, 122, 220, 322, 420, 519, 618, 717, 816, 914, 1014, 1113, 1212, 1311}, // 2042
|
||||||
|
{0, 210, 311, 410, 509, 607, 707, 805, 903, 1003, 1102, 1201, 1231}, // 2043
|
||||||
|
{7, 130, 229, 329, 428, 527, 625, 725, 823, 921, 1021, 1119, 1219, 1318}, // 2044
|
||||||
|
{0, 217, 319, 417, 517, 615, 714, 813, 911, 1010, 1109, 1208, 1307}, // 2045
|
||||||
|
{0, 206, 308, 406, 506, 604, 704, 802, 901, 930, 1029, 1128, 1227}, // 2046
|
||||||
|
{5, 126, 225, 326, 425, 525, 623, 723, 821, 920, 1019, 1117, 1217, 1315}, // 2047
|
||||||
|
{0, 214, 314, 413, 513, 611, 711, 810, 908, 1008, 1106, 1205, 1304}, // 2048
|
||||||
|
{0, 202, 304, 402, 502, 531, 630, 730, 828, 927, 1027, 1125, 1225}, // 2049
|
||||||
|
{3, 123, 221, 323, 421, 521, 619, 719, 817, 916, 1016, 1114, 1214, 1313}, // 2050
|
||||||
|
{0, 211, 313, 411, 510, 609, 708, 806, 905, 1005, 1103, 1203, 1302}, // 2051
|
||||||
|
{8, 201, 301, 331, 429, 528, 627, 726, 824, 923, 1022, 1121, 1221, 1320}, // 2052
|
||||||
|
{0, 219, 320, 419, 518, 616, 716, 814, 912, 1012, 1110, 1210, 1309}, // 2053
|
||||||
|
{0, 208, 309, 408, 508, 606, 705, 804, 902, 1001, 1031, 1129, 1229}, // 2054
|
||||||
|
{6, 128, 226, 328, 427, 526, 625, 724, 823, 921, 1020, 1119, 1218, 1317}, // 2055
|
||||||
|
{0, 215, 316, 415, 515, 613, 713, 811, 910, 1009, 1107, 1207, 1305}, // 2056
|
||||||
|
{0, 204, 305, 404, 504, 602, 702, 731, 830, 928, 1028, 1126, 1226}, // 2057
|
||||||
|
{4, 124, 223, 324, 423, 522, 621, 720, 819, 918, 1017, 1116, 1216, 1314}, // 2058
|
||||||
|
{0, 212, 314, 412, 512, 610, 710, 808, 907, 1006, 1105, 1205, 1304}, // 2059
|
||||||
|
{0, 202, 303, 401, 430, 530, 628, 727, 826, 924, 1024, 1123, 1223}, // 2060
|
||||||
|
{3, 121, 220, 322, 420, 519, 618, 717, 815, 914, 1013, 1112, 1212, 1311}, // 2061
|
||||||
|
{0, 209, 311, 410, 509, 607, 707, 805, 903, 1003, 1101, 1201, 1231}, // 2062
|
||||||
|
{7, 129, 228, 330, 428, 528, 626, 726, 824, 922, 1022, 1120, 1220, 1318}, // 2063
|
||||||
|
{0, 217, 318, 417, 516, 615, 714, 813, 911, 1010, 1109, 1208, 1307}, // 2064
|
||||||
|
{0, 205, 307, 406, 505, 604, 704, 802, 901, 930, 1029, 1128, 1227}, // 2065
|
||||||
|
{5, 126, 224, 326, 424, 524, 623, 722, 821, 919, 1019, 1117, 1217, 1315}, // 2066
|
||||||
|
{0, 214, 315, 414, 513, 612, 711, 810, 909, 1008, 1107, 1206, 1305}, // 2067
|
||||||
|
{0, 203, 304, 402, 502, 531, 629, 729, 828, 926, 1026, 1125, 1224}, // 2068
|
||||||
|
{4, 123, 221, 323, 421, 521, 619, 718, 817, 915, 1015, 1114, 1214, 1312}, // 2069
|
||||||
|
{0, 211, 312, 411, 510, 609, 708, 806, 905, 1004, 1103, 1203, 1301}, // 2070
|
||||||
|
{8, 131, 302, 331, 430, 529, 628, 727, 825, 924, 1023, 1122, 1221, 1320}, // 2071
|
||||||
|
{0, 219, 320, 418, 518, 616, 716, 814, 912, 1012, 1110, 1210, 1308}, // 2072
|
||||||
|
{0, 207, 309, 407, 507, 606, 705, 804, 902, 1001, 1031, 1129, 1229}, // 2073
|
||||||
|
{6, 127, 226, 327, 426, 526, 624, 724, 822, 921, 1020, 1119, 1218, 1317}, // 2074
|
||||||
|
{0, 215, 317, 415, 515, 613, 713, 812, 910, 1010, 1108, 1208, 1306}, // 2075
|
||||||
|
{0, 205, 305, 404, 503, 602, 701, 731, 829, 928, 1028, 1126, 1226}, // 2076
|
||||||
|
{4, 124, 223, 324, 423, 522, 620, 720, 818, 917, 1017, 1116, 1215, 1314}, // 2077
|
||||||
|
{0, 212, 314, 412, 512, 610, 709, 808, 906, 1006, 1105, 1204, 1303}, // 2078
|
||||||
|
{0, 202, 303, 402, 501, 531, 629, 728, 827, 925, 1025, 1123, 1223}, // 2079
|
||||||
|
{3, 122, 221, 321, 420, 519, 618, 717, 815, 914, 1013, 1111, 1211, 1310}, // 2080
|
||||||
|
{0, 209, 310, 409, 509, 607, 707, 805, 903, 1003, 1101, 1130, 1230}, // 2081
|
||||||
|
{7, 129, 227, 329, 428, 528, 626, 725, 824, 922, 1022, 1120, 1219, 1318}, // 2082
|
||||||
|
{0, 217, 318, 417, 517, 615, 715, 813, 912, 1011, 1110, 1209, 1308}, // 2083
|
||||||
|
{0, 206, 307, 405, 505, 603, 703, 802, 831, 930, 1029, 1128, 1227}, // 2084
|
||||||
|
{5, 126, 224, 326, 424, 523, 622, 722, 820, 919, 1019, 1117, 1217, 1315}, // 2085
|
||||||
|
{0, 214, 315, 414, 513, 611, 711, 809, 908, 1008, 1106, 1206, 1305}, // 2086
|
||||||
|
{0, 203, 305, 403, 503, 601, 630, 730, 828, 927, 1026, 1125, 1225}, // 2087
|
||||||
|
{4, 124, 222, 323, 421, 521, 619, 718, 817, 915, 1014, 1113, 1213, 1312}, // 2088
|
||||||
|
{0, 210, 312, 411, 510, 609, 708, 806, 904, 1004, 1102, 1202, 1301}, // 2089
|
||||||
|
{8, 130, 301, 331, 430, 529, 628, 727, 825, 924, 1023, 1121, 1221, 1320}, // 2090
|
||||||
|
{0, 218, 320, 419, 518, 617, 716, 815, 913, 1013, 1111, 1210, 1309}, // 2091
|
||||||
|
{0, 207, 308, 407, 506, 605, 705, 803, 902, 1001, 1031, 1129, 1229}, // 2092
|
||||||
|
{6, 127, 225, 327, 426, 525, 624, 723, 822, 921, 1020, 1119, 1218, 1317}, // 2093
|
||||||
|
{0, 215, 316, 415, 514, 613, 712, 811, 910, 1009, 1108, 1208, 1306}, // 2094
|
||||||
|
{0, 205, 306, 405, 504, 602, 702, 731, 830, 928, 1028, 1127, 1227}, // 2095
|
||||||
|
{4, 125, 224, 324, 423, 522, 620, 720, 818, 916, 1016, 1115, 1215, 1313}, // 2096
|
||||||
|
{0, 212, 314, 412, 512, 610, 709, 807, 906, 1005, 1104, 1204, 1302}, // 2097
|
||||||
|
{0, 201, 303, 402, 501, 531, 629, 728, 826, 925, 1024, 1123, 1222}, // 2098
|
||||||
|
{2, 121, 220, 322, 420, 520, 619, 718, 816, 915, 1014, 1112, 1212, 1310}, // 2099
|
||||||
|
{0, 209, 311, 410, 509, 608, 707, 806, 904, 1004, 1102, 1201, 1231}, // 2010
|
||||||
|
{7, 129, 228, 330, 428, 528, 626, 726, 825, 923, 1023, 1121, 1220, 1319}, //2101
|
||||||
|
{0, 217, 319, 417, 517, 616, 715, 814, 912, 1012, 1111, 1210, 1309}, //2102
|
||||||
|
{0, 207, 308, 407, 506, 605, 704, 803, 901, 1001, 1031, 1130, 1229}, //2103
|
||||||
|
{5, 128, 226, 327, 425, 524, 623, 722, 821, 919, 1019, 1118, 1217, 1316}, //2104
|
||||||
|
{0, 215, 316, 415, 514, 612, 712, 810, 908, 1008, 1107, 1206, 1305}, //2105
|
||||||
|
{0, 204, 306, 404, 504, 602, 701, 731, 829, 927, 1027, 1125, 1225}, //2106
|
||||||
|
{4, 124, 223, 325, 423, 523, 621, 720, 819, 917, 1016, 1115, 1214, 1313}, //2107
|
||||||
|
{0, 212, 313, 411, 511, 609, 709, 807, 906, 1005, 1103, 1203, 1301}, //2108
|
||||||
|
{9, 131, 302, 331, 430, 530, 628, 728, 826, 925, 1024, 1122, 1222, 1320}, //2109
|
||||||
|
{0, 219, 320, 419, 519, 617, 717, 816, 914, 1014, 1112, 1211, 1310}, //2110
|
||||||
|
{0, 208, 310, 408, 508, 606, 706, 805, 903, 1003, 1101, 1201, 1231}, //2111
|
||||||
|
{6, 129, 227, 328, 426, 526, 624, 724, 822, 921, 1021, 1119, 1219, 1318}, //2112
|
||||||
|
{0, 216, 318, 416, 515, 614, 713, 811, 910, 1010, 1108, 1208, 1307}, //2113
|
||||||
|
{0, 206, 307, 406, 505, 603, 703, 801, 830, 929, 1028, 1127, 1227}, //2114
|
||||||
|
{4, 126, 225, 326, 425, 524, 622, 722, 820, 918, 1018, 1116, 1216, 1315}, //2115
|
||||||
|
{0, 214, 314, 413, 512, 611, 710, 809, 907, 1006, 1105, 1204, 1303}, //2116
|
||||||
|
{0, 202, 303, 402, 502, 531, 630, 729, 828, 926, 1025, 1124, 1223}, //2117
|
||||||
|
{3, 122, 220, 322, 421, 520, 619, 719, 817, 916, 1015, 1113, 1213, 1311}, //2118
|
||||||
|
{0, 210, 311, 410, 509, 608, 708, 806, 905, 1004, 1103, 1202, 1301}, //2119
|
||||||
|
{7, 130, 229, 329, 428, 527, 626, 725, 824, 923, 1022, 1121, 1220, 1319}, //2120
|
||||||
|
{0, 217, 319, 417, 517, 615, 715, 813, 912, 1011, 1110, 1210, 1309}, //2121
|
||||||
|
{0, 207, 308, 407, 506, 605, 704, 802, 901, 930, 1030, 1129, 1229}, //2122
|
||||||
|
{5, 127, 226, 328, 426, 525, 624, 723, 821, 920, 1019, 1118, 1218, 1317}, //2123
|
||||||
|
{0, 215, 316, 414, 514, 612, 712, 810, 908, 1008, 1106, 1206, 1305}, //2124
|
||||||
|
{0, 203, 305, 404, 503, 602, 701, 731, 829, 927, 1027, 1125, 1225}, //2125
|
||||||
|
{4, 123, 222, 324, 423, 522, 621, 720, 819, 917, 1016, 1115, 1214, 1313}, //2126
|
||||||
|
{0, 211, 313, 412, 511, 610, 710, 808, 906, 1006, 1104, 1204, 1302}, //2127
|
||||||
|
{11, 201, 301, 331, 429, 529, 628, 727, 826, 924, 1024, 1122, 1222, 1320}, //2128
|
||||||
|
{0, 219, 320, 419, 518, 617, 716, 815, 914, 1013, 1112, 1211, 1310}, //2129
|
||||||
|
{0, 208, 310, 408, 508, 606, 705, 804, 903, 1002, 1101, 1201, 1230}, //2130
|
||||||
|
{6, 129, 227, 329, 427, 527, 625, 724, 823, 921, 1021, 1120, 1220, 1318}, //2131
|
||||||
|
{0, 217, 317, 416, 515, 614, 713, 811, 910, 1009, 1108, 1208, 1306}, //2132
|
||||||
|
{0, 205, 307, 405, 505, 603, 703, 801, 830, 928, 1028, 1127, 1226}, //2133
|
||||||
|
{5, 125, 224, 326, 424, 524, 622, 722, 820, 918, 1018, 1116, 1216, 1314}, //2134
|
||||||
|
{0, 213, 315, 413, 513, 612, 711, 809, 908, 1007, 1106, 1205, 1304}, //2135
|
||||||
|
{0, 202, 303, 401, 501, 531, 629, 729, 827, 926, 1025, 1124, 1223}, //2136
|
||||||
|
{2, 122, 220, 322, 420, 520, 618, 718, 817, 915, 1015, 1113, 1213, 1311}, //2137
|
||||||
|
{0, 210, 311, 410, 509, 608, 707, 806, 904, 1004, 1103, 1202, 1301}, //2138
|
||||||
|
{7, 130, 301, 330, 429, 528, 626, 726, 824, 923, 1023, 1122, 1221, 1320}, //2139
|
||||||
|
{0, 218, 319, 417, 517, 615, 714, 813, 911, 1011, 1110, 1209, 1308}, //2140
|
||||||
|
{0, 207, 308, 407, 506, 605, 704, 802, 901, 930, 1030, 1128, 1228}, //2141
|
||||||
|
{5, 127, 226, 327, 426, 525, 624, 723, 821, 919, 1019, 1117, 1217, 1316}, //2142
|
||||||
|
{0, 215, 316, 415, 515, 613, 713, 811, 909, 1008, 1107, 1206, 1305}, //2143
|
||||||
|
{0, 204, 304, 403, 503, 602, 701, 730, 829, 927, 1027, 1125, 1224}, //2144
|
||||||
|
{4, 123, 222, 323, 422, 522, 620, 720, 818, 917, 1016, 1115, 1214, 1313}, //2145
|
||||||
|
{0, 211, 312, 411, 511, 609, 709, 807, 906, 1006, 1104, 1204, 1302}, //2146
|
||||||
|
{0, 201, 302, 331, 430, 529, 628, 728, 826, 925, 1025, 1123, 1223}, //2147
|
||||||
|
{1, 121, 220, 320, 419, 518, 616, 716, 814, 913, 1013, 1111, 1211, 1310}, //2148
|
||||||
|
{0, 208, 310, 408, 508, 606, 705, 804, 902, 1002, 1031, 1130, 1230}, //2149
|
||||||
|
{6, 129, 227, 329, 427, 527, 625, 724, 822, 921, 1020, 1119, 1219, 1318}, //2150
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取农历日的表示
|
||||||
|
*
|
||||||
|
* @param lunarDay 农历日数值表示
|
||||||
|
* @return 农历日传统字符表示
|
||||||
|
*/
|
||||||
|
public static String getDayName(int lunarDay) {
|
||||||
|
return LunarDayName[lunarDay - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取农历月份
|
||||||
|
*
|
||||||
|
* @param lunarMonth 农历月数值表示
|
||||||
|
* @return 农历月传统字符表示
|
||||||
|
*/
|
||||||
|
public static char getMonthName(int lunarMonth) {
|
||||||
|
return LunarMonthName[lunarMonth - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取农历年份
|
||||||
|
*
|
||||||
|
* @param lunarYear 农历年数值表示
|
||||||
|
* @return 农历年传统字符表示
|
||||||
|
*/
|
||||||
|
public static String getYearName(int lunarYear) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(LunarYearName[lunarYear / 1000]);
|
||||||
|
sb.append(LunarYearName[lunarYear % 1000 / 100]);
|
||||||
|
sb.append(LunarYearName[lunarYear % 100 / 10]);
|
||||||
|
sb.append(LunarYearName[lunarYear % 10]);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回传统天干地支年名称
|
||||||
|
*
|
||||||
|
* @param y 农历年
|
||||||
|
* @return 传统农历年份的表示
|
||||||
|
*/
|
||||||
|
public static String getTraditionalYearName(int y) {
|
||||||
|
// 1804年是甲子年
|
||||||
|
y = y - 1804;
|
||||||
|
return ("" + LunarGan[y % 10] + LunarZhi[y % 12] + "年");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取生肖名
|
||||||
|
*
|
||||||
|
* @param y 农历年
|
||||||
|
* @return 生肖名
|
||||||
|
*/
|
||||||
|
public static char getAnimalYearName(int y) {
|
||||||
|
return LunarAnimalName[(y - 4) % 12];
|
||||||
|
}
|
||||||
|
}
|
||||||
98
src/main/java/com/github/heqiao2010/lunar/LunarUtils.java
Normal file
98
src/main/java/com/github/heqiao2010/lunar/LunarUtils.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package com.github.heqiao2010.lunar;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
public class LunarUtils {
|
||||||
|
/**
|
||||||
|
* 计算两个农历日期之差
|
||||||
|
*
|
||||||
|
* @param lc1 农历1
|
||||||
|
* @param lc2 农历2
|
||||||
|
* @param field 计算的维度,比如按月,天等
|
||||||
|
* @return 具体的差值
|
||||||
|
*/
|
||||||
|
public static long luanrDiff(LunarCalendar lc1, LunarCalendar lc2, int field) {
|
||||||
|
return solarDiff(lc1, lc2, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 求两个公历日期之差,field可以为年月日,时分秒<br>
|
||||||
|
* 一年按365天计算,一个月按30天计算<br>
|
||||||
|
*
|
||||||
|
* @param solar1 历日期
|
||||||
|
* @param solar2 历日期
|
||||||
|
* @param field 差值单位
|
||||||
|
* @return 差值
|
||||||
|
*/
|
||||||
|
public static long solarDiff(Calendar solar1, Calendar solar2, int field) {
|
||||||
|
long t1 = solar1.getTimeInMillis();
|
||||||
|
long t2 = solar2.getTimeInMillis();
|
||||||
|
switch (field) {
|
||||||
|
case Calendar.SECOND:
|
||||||
|
return (long) Math.rint((t1 - t2) / 1000.0);
|
||||||
|
case Calendar.MINUTE:
|
||||||
|
return (long) Math.rint((t1 - t2) / 60000.0); // 60 * 1000
|
||||||
|
case Calendar.HOUR:
|
||||||
|
return (long) Math.rint((t1 - t2) / 3600000.0); //3600 * 1000
|
||||||
|
case Calendar.DATE:
|
||||||
|
return (long) Math.rint((t1 - t2) / 86400000.0); // 24 * 3600 * 1000
|
||||||
|
case Calendar.MONTH:
|
||||||
|
return (long) Math.rint((t1 - t2) / 2592000000.0); // 30 * 24 * 3600 * 1000
|
||||||
|
case Calendar.YEAR:
|
||||||
|
return (long) Math.rint((t1 - t2) / 31536000000.0); // 365 * 24 * 3600 * 1000
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历月的天数
|
||||||
|
*
|
||||||
|
* @param lunarYear 农历年
|
||||||
|
* @param month 农历月
|
||||||
|
* @param isLeapMonth 闰月
|
||||||
|
* @return 天数,29或者30
|
||||||
|
*/
|
||||||
|
public static long lengthOfMonth(int lunarYear, int month, boolean isLeapMonth) {
|
||||||
|
short[] codes = LunarCodes.monthCodes(lunarYear);
|
||||||
|
int i = isLeapMonth ? month + 1 : month;
|
||||||
|
if (codes[0] > 0 && month > codes[0]) i++;
|
||||||
|
return LunarCodes.lengthOfMonth(lunarYear, month, codes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一个简单的二分查找,返回查找到的元素坐标,用于查找农历二维数组信息
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
* @param n 待查询数字
|
||||||
|
* @return 查到的坐标
|
||||||
|
*/
|
||||||
|
public static int binSearch(int[] array, int n) {
|
||||||
|
if (null == array || array.length == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int min = 0, max = array.length - 1;
|
||||||
|
if (n <= array[min]) {
|
||||||
|
return min;
|
||||||
|
} else if (n >= array[max]) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
while (max - min > 1) {
|
||||||
|
int newIndex = (max + min) / 2; // 二分
|
||||||
|
if (array[newIndex] > n) { // 取小区间
|
||||||
|
max = newIndex;
|
||||||
|
} else if (array[newIndex] < n) {// 取大区间
|
||||||
|
min = newIndex;
|
||||||
|
} else { // 相等,直接返回下标
|
||||||
|
return newIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (array[max] == n) {
|
||||||
|
return max;
|
||||||
|
} else if (array[min] == n) {
|
||||||
|
return min;
|
||||||
|
} else {
|
||||||
|
return min; // 返回 较小的一个
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ import net.mamoe.mirai.message.data.*
|
|||||||
import net.mamoe.mirai.message.data.Image.Key.queryUrl
|
import net.mamoe.mirai.message.data.Image.Key.queryUrl
|
||||||
import net.mamoe.mirai.utils.info
|
import net.mamoe.mirai.utils.info
|
||||||
import top.jie65535.mirai.tools.*
|
import top.jie65535.mirai.tools.*
|
||||||
|
import util.LunarDateUtil
|
||||||
import xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder
|
import xyz.cssxsh.mirai.hibernate.MiraiHibernateRecorder
|
||||||
import xyz.cssxsh.mirai.hibernate.entry.MessageRecord
|
import xyz.cssxsh.mirai.hibernate.entry.MessageRecord
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -207,7 +208,9 @@ object JChatGPT : KotlinPlugin(
|
|||||||
}
|
}
|
||||||
|
|
||||||
replace("{time}") {
|
replace("{time}") {
|
||||||
dateTimeFormatter.format(now)
|
val solarTime = dateTimeFormatter.format(now)
|
||||||
|
val lunarInfo = LunarDateUtil.getFormattedLunarAndHoliday(now)
|
||||||
|
"$solarTime\n农历$lunarInfo"
|
||||||
}
|
}
|
||||||
|
|
||||||
replace("{subject}") {
|
replace("{subject}") {
|
||||||
@@ -481,6 +484,17 @@ object JChatGPT : KotlinPlugin(
|
|||||||
|
|
||||||
private val thinkRegex = Regex("<think>[\\s\\S]*?</think>")
|
private val thinkRegex = Regex("<think>[\\s\\S]*?</think>")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 截断过长的工具输出,并添加省略标记
|
||||||
|
*/
|
||||||
|
private fun truncateToolOutput(content: String, maxLength: Int = PluginConfig.maxToolOutputLength): String {
|
||||||
|
if (content.length <= maxLength) return content
|
||||||
|
|
||||||
|
val truncated = content.take(maxLength)
|
||||||
|
val marker = "\n\n[系统提示:因内容过长,部分内容已被省略]"
|
||||||
|
return truncated + marker
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun startChat(event: MessageEvent) {
|
private suspend fun startChat(event: MessageEvent) {
|
||||||
if (!requestMap.add(event.subject.id)) {
|
if (!requestMap.add(event.subject.id)) {
|
||||||
logger.warning("The current Contact is busy!")
|
logger.warning("The current Contact is busy!")
|
||||||
@@ -880,6 +894,13 @@ object JChatGPT : KotlinPlugin(
|
|||||||
"工具调用失败,请尝试自行回答用户,或如实告知。\n异常信息:${e.message}"
|
"工具调用失败,请尝试自行回答用户,或如实告知。\n异常信息:${e.message}"
|
||||||
}
|
}
|
||||||
logger.info("Result=\"$result\"")
|
logger.info("Result=\"$result\"")
|
||||||
|
|
||||||
|
// 截断过长的工具输出
|
||||||
|
val truncatedResult = truncateToolOutput(result)
|
||||||
|
if (truncatedResult.length != result.length) {
|
||||||
|
logger.warning("工具 ${function.name} 返回内容过长,已从 ${result.length} 字符截断至 ${truncatedResult.length} 字符")
|
||||||
|
}
|
||||||
|
|
||||||
// 过会撤回加载消息
|
// 过会撤回加载消息
|
||||||
if (receipt != null) {
|
if (receipt != null) {
|
||||||
launch {
|
launch {
|
||||||
@@ -895,7 +916,7 @@ object JChatGPT : KotlinPlugin(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return truncatedResult
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -119,4 +119,7 @@ object PluginConfig : AutoSavePluginConfig("Config") {
|
|||||||
|
|
||||||
@ValueDescription("请求主人回复等待时间,单位毫秒,默认300秒")
|
@ValueDescription("请求主人回复等待时间,单位毫秒,默认300秒")
|
||||||
val requestOwnerWaitTimeout: Long by value(300000L)
|
val requestOwnerWaitTimeout: Long by value(300000L)
|
||||||
|
|
||||||
|
@ValueDescription("单个工具调用返回内容的最大字符数,超过将被截断并标注")
|
||||||
|
val maxToolOutputLength: Int by value(15000)
|
||||||
}
|
}
|
||||||
163
src/main/kotlin/util/LunarDateUtil.kt
Normal file
163
src/main/kotlin/util/LunarDateUtil.kt
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import com.github.heqiao2010.lunar.LunarCalendar
|
||||||
|
import com.github.heqiao2010.lunar.LunarCalendar.solar2Lunar
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
import java.util.Calendar
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 农历日期工具类
|
||||||
|
*/
|
||||||
|
object LunarDateUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取农历日期字符串
|
||||||
|
* @param offsetDateTime 公历日期时间
|
||||||
|
* @return 农历日期字符串,格式如:甲辰年(龙)十二月廿七
|
||||||
|
*/
|
||||||
|
fun getLunarDateString(offsetDateTime: OffsetDateTime): String {
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
calendar.set(
|
||||||
|
offsetDateTime.year,
|
||||||
|
offsetDateTime.monthValue - 1,
|
||||||
|
offsetDateTime.dayOfMonth
|
||||||
|
)
|
||||||
|
val lunar = solar2Lunar(calendar)
|
||||||
|
return lunar.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取农历信息(包含年份和生肖)
|
||||||
|
* @param offsetDateTime 公历日期时间
|
||||||
|
* @return 农历信息字符串
|
||||||
|
*/
|
||||||
|
fun getLunarInfo(offsetDateTime: OffsetDateTime): String {
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
calendar.set(
|
||||||
|
offsetDateTime.year,
|
||||||
|
offsetDateTime.monthValue - 1,
|
||||||
|
offsetDateTime.dayOfMonth
|
||||||
|
)
|
||||||
|
val lunar = solar2Lunar(calendar)
|
||||||
|
return lunar.getFullLunarName()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前日期的节假日信息
|
||||||
|
* @param offsetDateTime 公历日期时间
|
||||||
|
* @return 节假日名称,如果不是节假日则返回null
|
||||||
|
*/
|
||||||
|
fun getHoliday(offsetDateTime: OffsetDateTime): String? {
|
||||||
|
val month = offsetDateTime.monthValue
|
||||||
|
val day = offsetDateTime.dayOfMonth
|
||||||
|
val lunar = getLunarCalendar(offsetDateTime)
|
||||||
|
|
||||||
|
// 公历节日
|
||||||
|
when (month) {
|
||||||
|
1 -> {
|
||||||
|
if (day == 1) return "元旦"
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
if (day == 14) return "情人节"
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
if (day == 8) return "妇女节"
|
||||||
|
if (day == 12) return "植树节"
|
||||||
|
if (day == 15) return "消费者权益日"
|
||||||
|
}
|
||||||
|
4 -> {
|
||||||
|
if (day == 1) return "愚人节"
|
||||||
|
if (day == 4) return "清明节"
|
||||||
|
}
|
||||||
|
5 -> {
|
||||||
|
if (day == 1) return "劳动节"
|
||||||
|
if (day == 4) return "青年节"
|
||||||
|
}
|
||||||
|
6 -> {
|
||||||
|
if (day == 1) return "儿童节"
|
||||||
|
}
|
||||||
|
7 -> {
|
||||||
|
if (day == 1) return "建党节"
|
||||||
|
}
|
||||||
|
8 -> {
|
||||||
|
if (day == 1) return "建军节"
|
||||||
|
}
|
||||||
|
9 -> {
|
||||||
|
if (day == 10) return "教师节"
|
||||||
|
}
|
||||||
|
10 -> {
|
||||||
|
if (day == 1) return "国庆节"
|
||||||
|
}
|
||||||
|
12 -> {
|
||||||
|
if (day == 24) return "平安夜"
|
||||||
|
if (day == 25) return "圣诞节"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 农历节日
|
||||||
|
val lunarMonth = lunar.lunarMonth
|
||||||
|
val lunarDay = lunar.dayOfLunarMonth
|
||||||
|
|
||||||
|
when (lunarMonth) {
|
||||||
|
1 -> {
|
||||||
|
if (lunarDay == 1) return "春节"
|
||||||
|
if (lunarDay == 15) return "元宵节"
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
if (lunarDay == 2) return "龙抬头"
|
||||||
|
}
|
||||||
|
5 -> {
|
||||||
|
if (lunarDay == 5) return "端午节"
|
||||||
|
}
|
||||||
|
7 -> {
|
||||||
|
if (lunarDay == 7) return "七夕节"
|
||||||
|
}
|
||||||
|
8 -> {
|
||||||
|
if (lunarDay == 15) return "中秋节"
|
||||||
|
}
|
||||||
|
9 -> {
|
||||||
|
if (lunarDay == 9) return "重阳节"
|
||||||
|
}
|
||||||
|
12 -> {
|
||||||
|
if (lunarDay == 8) return "腊八节"
|
||||||
|
if (lunarDay == 23) return "小年" // 北方小年
|
||||||
|
if (lunarDay == 24) return "小年" // 南方小年
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 二十四节气(简化版,只判断几个主要的)
|
||||||
|
// 注意:这里使用简化的判断,实际节气计算比较复杂
|
||||||
|
// 可以使用更精确的节气计算库
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取LunarCalendar对象
|
||||||
|
*/
|
||||||
|
private fun getLunarCalendar(offsetDateTime: OffsetDateTime): LunarCalendar {
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
calendar.set(
|
||||||
|
offsetDateTime.year,
|
||||||
|
offsetDateTime.monthValue - 1,
|
||||||
|
offsetDateTime.dayOfMonth
|
||||||
|
)
|
||||||
|
return solar2Lunar(calendar)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取格式化的农历和节假日信息
|
||||||
|
* @param offsetDateTime 公历日期时间
|
||||||
|
* @return 格式化的字符串,如:农历甲辰年(龙)十二月廿七 春节
|
||||||
|
*/
|
||||||
|
fun getFormattedLunarAndHoliday(offsetDateTime: OffsetDateTime): String {
|
||||||
|
val lunarInfo = getLunarInfo(offsetDateTime)
|
||||||
|
val holiday = getHoliday(offsetDateTime)
|
||||||
|
|
||||||
|
return if (holiday != null) {
|
||||||
|
"$lunarInfo $holiday"
|
||||||
|
} else {
|
||||||
|
lunarInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user