参考:http://www.cnblogs.com/qintangtao/archive/2013/03/01/2938887.html
节气的计算有些误差,但是基本上满足要求。
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Lunar {
private Calendar cal;
private int year;// 农历年
private int month;// 农历月
private int day;// 农历日
private boolean leap;// 是否闰年
final static String chineseNumber[] = { "一", "二", "三", "四", "五", "六", "七",
"八", "九", "十", "十一", "十二" };
final static String Big_Or_Small[] = { "大", "小", "大", "小", "大", "小", "大",
"大", "小", "大", "小", "大" };
private static String[] SolarTerm = new String[] { "小寒", "大寒", "立春", "雨水",
"惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋",
"处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至" };
private static int[] sTermInfo = new int[] { 0, 21208, 42467, 63836, 85337,
107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343,
285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795,
462224, 483532, 504758 };
// 公历节日
private static class SolarHolidayStruct {
public int Month;
public int Day;
public int Recess; // 假期长度
public String HolidayName;
public SolarHolidayStruct(int month, int day, int recess, String name) {
Month = month;
Day = day;
Recess = recess;
HolidayName = name;
}
}
// 农历节日
private static class LunarHolidayStruct {
public int Month;
public int Day;
public int Recess;
public String HolidayName;
public LunarHolidayStruct(int month, int day, int recess, String name) {
Month = month;
Day = day;
Recess = recess;
HolidayName = name;
}
}
// 按农历计算的节日
private static LunarHolidayStruct[] lHolidayInfo = new LunarHolidayStruct[] {
new LunarHolidayStruct(1, 1, 1, "春节"),
new LunarHolidayStruct(1, 15, 0, "元宵节"), new LunarHolidayStruct(5, 5, 0, "端午节"),
new LunarHolidayStruct(7, 7, 0, "七夕情人节"), new LunarHolidayStruct(7, 15, 0, "中元节 盂兰盆节"),
new LunarHolidayStruct(8, 15, 0, "中秋节"), new LunarHolidayStruct(9, 9, 0, "重阳节"),
new LunarHolidayStruct(12, 8, 0, "腊八节"), new LunarHolidayStruct(12, 23, 0, "北方小年(扫房)"),
new LunarHolidayStruct(12, 24, 0, "南方小年(掸尘)") // new LunarHolidayStruct(12, 30, 0, "除夕") //注意除夕需要其它方法进行计算
}; // 按公历计算的节日
private static SolarHolidayStruct[] sHolidayInfo = new SolarHolidayStruct[] { new SolarHolidayStruct(1, 1, 1, "元旦"),
new SolarHolidayStruct(2, 2, 0, "世界湿地日"), new SolarHolidayStruct(2, 10, 0, "国际气象节"),
new SolarHolidayStruct(2, 14, 0, "情人节"), new SolarHolidayStruct(3, 1, 0, "国际海豹日"),
new SolarHolidayStruct(3, 5, 0, "学雷锋纪念日"), new SolarHolidayStruct(3, 8, 0, "妇女节"),
new SolarHolidayStruct(3, 12, 0, "植树节 孙中山逝世纪念日"), new SolarHolidayStruct(3, 14, 0, "国际警察日"),
new SolarHolidayStruct(3, 15, 0, "消费者权益日"), new SolarHolidayStruct(3, 17, 0, "中国国医节 国际航海日"),
new SolarHolidayStruct(3, 21, 0, "世界森林日 消除种族歧视国际日 世界儿歌日"), new SolarHolidayStruct(3, 22, 0, "世界水日"),
new SolarHolidayStruct(3, 24, 0, "世界防治结核病日"), new SolarHolidayStruct(4, 1, 0, "愚人节"),
new SolarHolidayStruct(4, 7, 0, "世界卫生日"), new SolarHolidayStruct(4, 22, 0, "世界地球日"),
new SolarHolidayStruct(5, 1, 1, "劳动节"), new SolarHolidayStruct(5, 2, 1, "劳动节假日"),
new SolarHolidayStruct(5, 3, 1, "劳动节假日"), new SolarHolidayStruct(5, 4, 0, "青年节"),
new SolarHolidayStruct(5, 8, 0, "世界红十字日"), new SolarHolidayStruct(5, 12, 0, "国际护士节"),
new SolarHolidayStruct(5, 31, 0, "世界无烟日"), new SolarHolidayStruct(6, 1, 0, "国际儿童节"),
new SolarHolidayStruct(6, 5, 0, "世界环境保护日"), new SolarHolidayStruct(6, 26, 0, "国际禁毒日"),
new SolarHolidayStruct(7, 1, 0, "建党节 香港回归纪念 世界建筑日"), new SolarHolidayStruct(7, 11, 0, "世界人口日"),
new SolarHolidayStruct(8, 1, 0, "建军节"), new SolarHolidayStruct(8, 8, 0, "中国男子节 父亲节"),
new SolarHolidayStruct(8, 15, 0, "抗日战争胜利纪念"), new SolarHolidayStruct(9, 9, 0, " 逝世纪念"),
new SolarHolidayStruct(9, 10, 0, "教师节"), new SolarHolidayStruct(9, 18, 0, "九·一八事变纪念日"),
new SolarHolidayStruct(9, 20, 0, "国际爱牙日"), new SolarHolidayStruct(9, 27, 0, "世界旅游日"),
new SolarHolidayStruct(9, 28, 0, "孔子诞辰"), new SolarHolidayStruct(10, 1, 1, "国庆节 国际音乐日"),
new SolarHolidayStruct(10, 2, 1, "国庆节假日"), new SolarHolidayStruct(10, 3, 1, "国庆节假日"),
new SolarHolidayStruct(10, 6, 0, "老人节"), new SolarHolidayStruct(10, 24, 0, "联合国日"),
new SolarHolidayStruct(11, 10, 0, "世界青年节"), new SolarHolidayStruct(11, 12, 0, "孙中山诞辰纪念"),
new SolarHolidayStruct(12, 1, 0, "世界艾滋病日"), new SolarHolidayStruct(12, 3, 0, "世界残疾人日"),
new SolarHolidayStruct(12, 20, 0, "澳门回归纪念"), new SolarHolidayStruct(12, 24, 0, "平安夜"),
new SolarHolidayStruct(12, 25, 0, "圣诞节"), new SolarHolidayStruct(12, 26, 0, " 诞辰纪念") }; // 星座名称
private static String[] _constellationName = { "白羊座", "金牛座", "双子座", "巨蟹座",
"狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座", "水瓶座", "双鱼座" };
static SimpleDateFormat chineseDateFormat = new SimpleDateFormat(
" yyyy年MM月dd日 ");
final static 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 };
/**
* 传回农历 y年的总天数
*/
final private static int yearDays(int y) {
int i, sum = 348;
for (i = 0x8000; i > 0x8; i >>= 1) {
if ((lunarInfo[y - 1900] & i) != 0)
sum += 1;
}
return (sum + leapDays(y)); }
/**
* 传回农历 y年闰月的天数
*/
final private static int leapDays(int y) {
if (leapMonth(y) != 0) { if ((lunarInfo[y - 1900] & 0x10000) != 0)
return 30; else
return 29;
} else
return 0;
}
/**
* 传回农历 y年闰哪个月 1-12 , 没闰传回 0
*/
final private static int leapMonth(int y) {
return (int) (lunarInfo[y - 1900] & 0xf);
}
/**
* 传回农历 y年m月的总天数
*/
final private static int monthDays(int y, int m) {
if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) return 29;
else
return 30;
}
/**
* 传回农历 y年的生肖
*/
final public String animalsYear() {
final String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
return Animals[(year - 4) % 12];
}
/**
* 传入 月日的offset 传回干支, 0=甲子
*/
final private static String cyclicalm(int num) {
final String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚",
"辛", "壬", "癸" };
final String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午",
"未", "申", "酉", "戌", "亥" }; return (Gan[num % 10] + Zhi[num % 12]);
}
/**
* 传入 offset 传回干支, 0=甲子
*/
final public String cyclical() {
int num = year - 1900 + 36;
return (cyclicalm(num));
}
public Lunar(Calendar cal) {
this.cal = cal;
@SuppressWarnings(" unused ")
int yearCyl, monCyl, dayCyl;
int leapMonth = 0;
Date baseDate = null; try {
baseDate = chineseDateFormat.parse(" 1900年1月31日 ");
} catch (ParseException e) { e.printStackTrace(); // To change body of catch statement use
// Options | File Templates.
} // 求出和1900年1月31日相差的天数
int offset = (int) ((cal.getTime().getTime() - baseDate.getTime()) / 86400000L);
dayCyl = offset + 40;
monCyl = 14;
// 用offset减去每农历年的天数
// 计算当天是农历第几天
// i最终结果是农历的年份
// offset是当年的第几天
int iYear, daysOfYear = 0;
for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) {
daysOfYear = yearDays(iYear);
offset -= daysOfYear;
monCyl += 12;
}
if (offset < 0) {
offset += daysOfYear;
iYear--;
monCyl -= 12;
}
// 农历年份
year = iYear;
yearCyl = iYear - 1864;
leapMonth = leapMonth(iYear); // 闰哪个月,1-12
leap = false;
// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
int iMonth, daysOfMonth = 0;
for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
// 闰月
if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) { --iMonth;
leap = true;
daysOfMonth = leapDays(year); } else
daysOfMonth = monthDays(year, iMonth);
offset -= daysOfMonth; // 解除闰月
if (leap && iMonth == (leapMonth + 1))
leap = false;
if (!leap)
monCyl++;
}
// offset为0时,并且刚才计算的月份是闰月,要校正
if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
if (leap) {
leap = false;
} else {
leap = true;
--iMonth;
--monCyl;
}
}
// offset小于0时,也要校正
if (offset < 0) {
offset += daysOfMonth;
--iMonth;
--monCyl;
}
month = iMonth;
day = offset + 1;
}
public static String getChinaDayString(int day) {
String chineseTen[] = { "初", "十", "廿", "卅" };
int n = day % 10 == 0 ? 9 : day % 10 - 1; if (day > 30)
return "";
if (day == 10)
return "初十"; else
return chineseTen[day / 10] + chineseNumber[n];
}
public String toString() {
return /* cyclical() + "年" + */(leap ? "闰" : "")
+ chineseNumber[month - 1] + "月"+ getChinaDayString(day);
}
/**
* 返回阿拉伯数字的阴历日期
*/
public String numeric_md() {
String temp_day;
String temp_mon; temp_mon = month < 10 ? "0" + month : "" + month;
temp_day = day < 10 ? "0" + day : "" + day;
return temp_mon + temp_day;
}
/**
* 返回阴历的月份
*/
public String get_month() {
return chineseNumber[month - 1];
}
/**
* 返回阴历的天
*/
public String get_date() {
return getChinaDayString(day);
}
/**
* 返回的月份的大或小
*/
public String get_Big_Or_Small() {
return Big_Or_Small[month - 1];
}
/**
* 计算并返回中国农历节日
*/
public String getChineseHoliday() {
String tempStr = "";
if (this.leap == false) // 闰月不计算节日
{ for (LunarHolidayStruct lh : lHolidayInfo) {
if ((lh.Month == this.month) && (lh.Day == this.day)) {
tempStr = lh.HolidayName;
break;
}
}
// 对除夕进行特别处理
if (this.month == 12) {
int i = monthDays(this.year, 12); // 计算当年农历12月的总天数
if (this.day == i)// 如果为最后一天
{
tempStr = "除夕";
}
}
} return tempStr;
}
/**
* 按公历计算的节日
*/
public String getDateHoliday() {
String tempStr = "";
for (SolarHolidayStruct sh : sHolidayInfo) { if ((sh.Month == cal.get(Calendar.MONTH) + 1)
&& (sh.Day == cal.get(Calendar.DAY_OF_MONTH))) {
tempStr = sh.HolidayName;
break;
}
}
return tempStr;
}
/**
* 定气法计算二十四节气
*/
public String getChineseTwentyFourDay() {
// //#1/6/1900 2:05:00 AM#
Calendar ca = Calendar.getInstance();
ca.set(1900, 0, 6, 2, 5, 0); Calendar newDate = null;
final Date baseDateAndTime = ca.getTime();
double num; int y;
String tempStr = "";
y = this.cal.get(Calendar.YEAR); for (int i = 1; i <= 24; i++) {
num = 525948.76 * (y - 1900) + sTermInfo[i - 1]; newDate = Calendar.getInstance();
newDate.setTime(baseDateAndTime);
newDate.add(Calendar.MINUTE, (int) Math.ceil(num) + 5);// 按分钟计算//(int)Math.ceil(num)+5
// 找来这个计算方法不晓得+5么意思,地址:http://hi.baidu.com/1039580989/item/4fe7743d00394389b711db02
if (newDate.get(Calendar.DAY_OF_YEAR) == this.cal
.get(Calendar.DAY_OF_YEAR)) {
tempStr = SolarTerm[i - 1];
break;
}
}
return tempStr;
}
/**
* 返回星座
*/
public String getConstellation() {
int index = 0;
int y, m, d;
y = this.cal.get(Calendar.YEAR);
m = this.cal.get(Calendar.MONTH);
d = this.cal.get(Calendar.DAY_OF_MONTH);
y = m * 100 + d;
if (((y >= 321) && (y <= 419))) {
index = 0; } else if ((y >= 420) && (y <= 520)) {
index = 1; } else if ((y >= 521) && (y <= 620)) {
index = 2; } else if ((y >= 621) && (y <= 722)) {
index = 3; } else if ((y >= 723) && (y <= 822)) {
index = 4; } else if ((y >= 823) && (y <= 922)) {
index = 5; } else if ((y >= 923) && (y <= 1022)) {
index = 6; } else if ((y >= 1023) && (y <= 1121)) {
index = 7; } else if ((y >= 1122) && (y <= 1221)) {
index = 8; } else if ((y >= 1222) || (y <= 119)) {
index = 9; } else if ((y >= 120) && (y <= 218)) {
index = 10; } else if ((y >= 219) && (y <= 320)) {
index = 11; } else {
index = 0; }
return _constellationName[index];
}
}