org.erjia.lang.chinese.calendar.ChineseCalendar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lang Show documentation
Show all versions of lang Show documentation
Java 开发工具包 ErJia2,是 ErJia 的升级版,向 Kotlin 迁移。“ErJia”,是以作者生活的村落”二甲村”而来,为了纪念这座美好的小村庄,特意将该工具包以“二甲”的拼音命名。
The newest version!
package org.erjia.lang.chinese.calendar;
import org.erjia.lang.helper.StringHelper;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* @author linshuaishuai
*/
public class ChineseCalendar {
public static enum TianGan {
JIA ("甲"),
YI ("乙"),
BING("丙"),
DING("丁"),
WU ("戊"),
JI ("己"),
GENG("庚"),
XIN ("辛"),
REN ("壬"),
GUI ("癸");
private String name;
TianGan(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public static enum DiZhi {
ZI ("子"),
CHOU("丑"),
YAN ("寅"),
MAO ("卯"),
CHEN("辰"),
SI ("巳"),
WU ("午"),
WEI ("未"),
SHEN("申"),
YOU ("酉"),
XV ("戌"),
HAI ("亥");
private String name;
DiZhi(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public static enum ShengXiao {
SHU ("鼠"),
NIU ("牛"),
HU ("虎"),
TU ("兔"),
LONG("龙"),
SHE ("蛇"),
MA ("马"),
YANG("羊"),
HOU ("猴"),
JI ("鸡"),
GOU ("狗"),
ZHU ("猪");
private String name;
ShengXiao(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public static class Year {
private int value;
private TianGan tg;
private DiZhi dz;
public Year(int value) {
}
public int getValue() {
return value;
}
public TianGan getGan() {
return tg;
}
public DiZhi getZhi() {
return dz;
}
}
private static final long[] lunarInfo = new long[] { 0x04bd8, 0x04ae0,
0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0,
0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540,
0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5,
0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3,
0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0,
0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0,
0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8,
0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570,
0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5,
0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0,
0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50,
0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0,
0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7,
0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50,
0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954,
0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260,
0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0,
0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0,
0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20,
0x0ada0 };
private static final int[] year20 = new int[] { 1, 4, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1 };
private static final int[] year19 = new int[] { 0, 3, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 };
private static final int[] year2000 = new int[] { 0, 3, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1 };
private static final String[] nStr1 = new String[] { "", "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊" };
private static final String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };
private static final String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };
private static final String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
private static final String[] solarTerm = new String[] {
"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨",
"立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑",
"白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"
};
private static final String[] lFtv = new String[] { "0101*农历春节", "0115 元宵节", "0505 端午节", "0707 七夕情人节", "0815 中秋节", "0909 重阳节", "1208 腊八节", "1224 小年", "0100*除夕" };
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 EEEEE");
private Calendar gregorianCalendar;
private ChineseCalendar(Calendar gregorianCalendar) {
this.gregorianCalendar = gregorianCalendar;
}
public static ChineseCalendar getInstance() {
return new ChineseCalendar(Calendar.getInstance());
}
public static ChineseCalendar getInstance(Calendar gregorianCalendar) {
return new ChineseCalendar(gregorianCalendar);
}
/**
* 计算农历一年的天数
* @return 该年的天数
*/
public final int daysOfYear() {
return daysOfYear(getGregorianYear());
}
/**
* 计算农历闰月的天数
* @return 该年闰月的天数
*/
public final int daysOfLeapMonth() {
return daysOfLeapMonth(getGregorianMonth());
}
/**
* 计算该年闰月的月份(1-12), 没闰月返回 0。
* @return 该年闰月的月份
*/
public final int getLeapMonth() {
return getLeapMonth(getGregorianYear());
}
/**
* 计算该月的总天数
* @return 该月的天数
*/
public final int daysOfMonth() {
return daysOfMonth(getGregorianYear(), getGregorianMonth());
}
/**
* 获得干支年
* @return 干支年
*/
public final String getYear() {
int num = (int) (calElement()[0] - 1900 + 36);
return (Gan[num % 10] + Zhi[num % 12]);
}
/**
* 获得月份
* @return 月份
*/
public final String getMonth() {
long[] elements = calElement();
return nStr1[(int) elements[1]];
}
/**
* 获得日
* @return 日
*/
public final String getDay() {
long[] elements = calElement();
return toChineseDay((int) (elements[2]));
}
/**
* 根据Calendar的字段获取相应的值
* @param field 字段
* @return 年/月/日
*/
public final String get(int field) {
switch (field) {
case Calendar.YEAR: return getYear();
case Calendar.MONTH: return getMonth();
case Calendar.DAY_OF_MONTH: return getDay();
default: return null;
}
}
/**
* 获得生肖
* @return 生肖
*/
public final String getZodiac() {
return Animals[(int) ((calElement()[0] - 4) % 12)];
}
/**
* 传出y年m月d日对应的农历.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6
*
* @return
*/
private long[] calElement() {
return calElement(getGregorianYear(), getGregorianMonth(), getGregorianDay());
}
/**
* 传出y年m月d日对应的农历.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6
*/
private long[] calElement(int y, int m, int d) {
long[] nongDate = new long[7];
int i = 0, temp = 0, leap = 0;
Date baseDate = new GregorianCalendar(0 + 1900, 0, 31).getTime();
Date objDate = new GregorianCalendar(y, m - 1, d).getTime();
long offset = (objDate.getTime() - baseDate.getTime()) / 86400000L;
nongDate[5] = offset + 40;
nongDate[4] = 14;
for (i = 1900; i < 2050 && offset > 0; i++) {
temp = daysOfYear(i);
offset -= temp;
nongDate[4] += 12;
}
if (offset < 0) {
offset += temp;
i--;
nongDate[4] -= 12;
}
nongDate[0] = i;
nongDate[3] = i - 1864;
leap = getLeapMonth(i); // 闰哪个月
nongDate[6] = 0;
for (i = 1; i < 13 && offset > 0; i++) {
// 闰月
if (leap > 0 && i == (leap + 1) && nongDate[6] == 0) {
--i;
nongDate[6] = 1;
temp = daysOfLeapMonth((int) nongDate[0]);
} else {
temp = daysOfMonth((int) nongDate[0], i);
}
// 解除闰月
if (nongDate[6] == 1 && i == (leap + 1))
nongDate[6] = 0;
offset -= temp;
if (nongDate[6] == 0)
nongDate[4]++;
}
if (offset == 0 && leap > 0 && i == leap + 1) {
if (nongDate[6] == 1) {
nongDate[6] = 0;
} else {
nongDate[6] = 1;
--i;
--nongDate[4];
}
}
if (offset < 0) {
offset += temp;
--i;
--nongDate[4];
}
nongDate[1] = i;
nongDate[2] = offset + 1;
return nongDate;
}
/**
* 将公历日的名称转换为阴历日名称
* @param day 公历日
* @return 阴历日
*/
public static String toChineseDay(int day) {
String result = StringHelper.EMPTY;
switch (day) {
case 10: return "初十";
case 20: return "二十";
case 30: return "三十";
default:
break;
}
int two = ((day) / 10);
switch (two) {
case 0: result = "初"; break;
case 1: result = "十"; break;
case 2: result = "廿"; break;
case 3: result = "三"; break;
default:
break;
}
int one = (day % 10);
switch (one) {
case 1: result += "一"; break;
case 2: result += "二"; break;
case 3: result += "三"; break;
case 4: result += "四"; break;
case 5: result += "五"; break;
case 6: result += "六"; break;
case 7: result += "七"; break;
case 8: result += "八"; break;
case 9: result += "九"; break;
}
return result;
}
private int getGregorianYear() {
return gregorianCalendar.get(Calendar.YEAR);
}
private int getGregorianMonth() {
return gregorianCalendar.get(Calendar.MONTH) + 1;
}
private int getGregorianDay() {
return gregorianCalendar.get(Calendar.DAY_OF_MONTH);
}
private static int daysOfYear(int year) {
int i, sum = 348;
for (i = 0x8000; i > 0x8; i >>= 1) {
if ((lunarInfo[year - 1900] & i) != 0)
sum += 1;
}
return (sum + daysOfLeapMonth(year));
}
private static int daysOfLeapMonth(int year) {
if (getLeapMonth(year) != 0) {
if ((lunarInfo[year - 1900] & 0x10000) != 0) {
return 30;
}
else {
return 29;
}
} else {
return 0;
}
}
private static int getLeapMonth(int year) {
return (int) (lunarInfo[year - 1900] & 0xf);
}
private static int daysOfMonth(int year, int month) {
if ((lunarInfo[year - 1900] & (0x10000 >> month)) == 0) {
return 29;
} else {
return 30;
}
}
@Override
public final String toString() {
long[] l = calElement();
StringBuilder sToday = new StringBuilder();
sToday.append(getYear());
sToday.append('(');
sToday.append(getZodiac());
sToday.append(")年");
sToday.append(getMonth());
sToday.append("月");
if (l[6] == 1) {
sToday.append("(润)");
}
sToday.append(toChineseDay((int) (l[2])));
return sToday.toString();
}
}