阳历转阴历

例如调整一月为正月、十二月为腊月,年份调整为阴历年份等。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class Lunar {
private int year;
private int month;
private int day;
private boolean leap;
final static String chineseNumber[] = {"正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊"};
final static String chineseNumber1[] = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"};
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));
}

/**
* 传出y年m月d日对应的农历.
* yearCyl3:农历年与1864的相差数 ?
* monCyl4:从1900年1月31日以来,闰月数
* dayCyl5:与1900年1月31日相差的天数,再加40 ?
*
* @param cal
* @return
*/
public Lunar(Calendar cal) {
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] + chineseNumber1[n];
}

public String toString() {
return (leap ? "闰" : "") + chineseNumber[month - 1] + "月" + getChinaDayString(day);
}
public String getChinaWeekdayString(String weekday){
if(weekday.equals("Mon"))
return "一";
if(weekday.equals("Tue"))
return "二";
if(weekday.equals("Wed"))
return "三";
if(weekday.equals("Thu"))
return "四";
if(weekday.equals("Fri"))
return "五";
if(weekday.equals("Sat"))
return "六";
if(weekday.equals("Sun"))
return "日";
else
return "";

}
public static void main(String[] args) throws ParseException{
Calendar today = Calendar.getInstance();
today.setTime(new java.util.Date());//加载当前日期
//today.setTime(chineseDateFormat.parse("2006年10月30日"));//加载自定义日期
Lunar lunar = new Lunar(today);
System.out.print(lunar.cyclical()+"年");//计算输出阴历年份
System.out.println(lunar.toString());//计算输出阴历日期
System.out.println(lunar.animalsYear());//计算输出属相
System.out.println(new java.sql.Date(today.getTime().getTime()));//输出阳历日期
System.out.println("星期"+lunar.getChinaWeekdayString(today.getTime().toString().substring(0,3)));//计算输出星期几
}
}



















1. package lunarcalendae;
2.
3. import java.text.ParseException;
4. import java.text.SimpleDateFormat;
5. import java.util.Date;
6.
7. public class Lunar {
8.
9. private static Date TheDate = null;
10. private int cYear;
11. private int cMonth;
12. private int cDay;
13. private int cHour;
14. //天干
15. private String tgString = "甲乙丙丁戊己庚辛壬癸";
16. //地支
17. private String dzString = "子丑寅卯辰巳午未申酉戌亥";
18. //中文数字
19. pr

ivate String numString = "一二三四五六七八九十";
20. //阴历中的月称
21. private String monString = "正二三四五六七八九十冬腊";
22. //星期的中文
23. private String weekString = "日一二三四五六";
24. //生肖
25. private String sx = "鼠牛虎兔龙蛇马羊猴鸡狗猪";
26. private SimpleDateFormat chineseDateFormat = new SimpleDateFormat(
27. "yyyy年MM月dd日");
28.
29. //1900年到2050年的阴历推算信息
30. private long[] CalendarData = new long[] { 0x8096d, 0x4ae, 0xa57, 0x50a4d,
31. 0xd26, 0xd95, 0x40d55, 0x56a, 0x9ad, 0x2095d, 0x4ae, 0x6149b,
32. 0xa4d, 0xd25, 0x51aa5, 0xb54, 0xd6a, 0x212da, 0x95b, 0x70937,
33. 0x497, 0xa4b, 0x5164b, 0x6a5, 0x6d4, 0x415b5, 0x2b6, 0x957,
34. 0x2092f, 0x497, 0x60c96, 0xd4a, 0xea5, 0x50d69, 0x5ad, 0x2b6,
35. 0x3126e, 0x92e, 0x7192d, 0xc95, 0xd4a, 0x61b4a, 0xb55, 0x56a,
36. 0x4155b, 0x25d, 0x92d, 0x2192b, 0xa95, 0x71695, 0x6ca, 0xb55,
37. 0x50ab5, 0x4da, 0xa5d, 0x30a57, 0x52d, 0x8152a, 0xe95, 0x6aa,
38. 0x615aa, 0xab5, 0x4b6, 0x414ae, 0xa57, 0x526, 0x31d26, 0xd95,
39. 0x70b55, 0x56a, 0x96d, 0x5095d, 0x4ad, 0xa4d, 0x41a4d, 0xd25,
40. 0x81aa5, 0xb54, 0xb5a, 0x612da, 0x95b, 0x49b, 0x41497, 0xa4b,
41. 0xa164b, 0x6a5, 0x6d4, 0x615b4, 0xab6, 0x957, 0x5092f, 0x497,
42. 0x64b, 0x30d4a, 0xea5, 0x80d65, 0x55c, 0xab6, 0x5126d, 0x92e,
43. 0xc96, 0x41a95, 0xd4a, 0xda5, 0x20b55, 0x56a, 0x7155b, 0x25d,
44. 0x92d, 0x5192b, 0xa95, 0xb4a, 0x416aa, 0xad5, 0x90ab5, 0x4ba,
45. 0xa5b, 0x60a57, 0x52b, 0xa93, 0x40e95, 0x6aa, 0xad5, 0x209b5,
46. 0x4b6, 0x614ae, 0xa4e, 0xd26, 0x51d26, 0xd53, 0x5aa, 0x30d6a,
47. 0x96d, 0x7095d, 0x4ad, 0xa4d, 0x61a4b, 0xd25, 0xd52, 0x51b54,
48. 0xb5a, 0x56d, 0x2095b, 0x49b, 0x71497, 0xa4b, 0xaa5, 0x516a5,
49. 0x6d2, 0xada };
50.
51. //存放每月一日到每年1月1日的天数,二月都以28天计算
52. private int[] madd = new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243,
53. 273, 304, 334 };
54.
55. //位运算,主要用来从十六进制中得到阴历每个月份是大月还是小月
56. private int GetBit(long m, int n) {
57. int r = (int) ((m >> n) & 1);
58. return r;
59. }
60.
61. //将阳历向阴历转换
62. @SuppressWarnings("deprecation")
63. public void e2c(String time) throws ParseException {
64. TheDate = chineseDateFormat.parse(time);
65. int total, m, n, k;
66. boolean isEnd = false;
67. int tmp = TheDate.getYear();
68.

if (tmp < 1900) {
69. tmp += 1900;
70. }
71.
72. //计算TheDate到1900年1月30日的总天数,1900年1月31日是“庚子年正月初一”我们以这个时间点来推测
73. total = (int) ((tmp - 1900) * 365/*先以每年365天粗算*/
74. + countLeapYears(1900, tmp)/*再加上其中的闰年2月多出的一天*/
75. + madd[TheDate.getMonth()]/*当前时间月份到元旦的天数*/
76. + TheDate.getDate()/*载加上当前月份已过天数*/
77. - 30/*因为1900年1月31日才是正月初一,粗算时多算了30天*/);
78. //判断当前年份是否是闰年,如果为闰年并且二月已过,应再加上2月多的一天,才是准确的总天数
79. if (isLeapYear(tmp) && TheDate.getMonth() > 1)
80. total++;
81. //开始推算已经过了几个阴历年,从1900年开始
82. for (m = 0;; m++) {
83. //检查16进制中信息,当年是否有闰月,有,则为13个月份
84. k = (CalendarData[m] < 0xfff) ? 11 : 12;
85.
86. for (n = k; n >= 0; n--) {
87. //如果总天数被减得小于29或30(由16进制中的规律来确定),则推算结束
88. if (total <= 29 + GetBit(CalendarData[m], n)) {
89. isEnd = true;
90. break;
91. }
92. //如果不小于29或30,则继续做减
93. total = total - 29 - GetBit(CalendarData[m], n);
94. }
95. if (isEnd)
96. break;
97. }
98. //当前阴历年份
99. cYear = 1900 + m;
100. //当前阴历月份
101. cMonth = k - n + 1;
102. //当前阴历日子
103. cDay = total;
104.
105. //如果阴历cYear年有闰月,则确定是闰几月,并精确阴历月份
106. if (k == 12) {
107. //如果cMonth恰巧等于该年闰月,则需要标示当前阴历月份为闰月
108. if (cMonth == Math.floor(CalendarData[m] / 0x10000) + 1){
109. cMonth = 1 - cMonth;
110. }
111. //如果cMonth大于该年闰月,则表示闰月已过,需要对cMonth减1
112. if (cMonth > Math.floor(CalendarData[m] / 0x10000) + 1){
113. cMonth--;
114. }
115. }
116. //计算时辰,夜里23点到1点为子时,每两个小时为一个时辰,用“地支”依次类推
117. cHour = (int) Math.floor((TheDate.getHours() + 3) / 2);
118. }
119.
120. //整理输出
121. public String getcDateString() {


122. String tmp = "";
123. //算天干,1900年1月31日是庚子年,庚是天干中的第七位需要对cYear-4再做模运算
124. tmp += tgString.charAt((cYear - 4) % 10); // 年干
125. tmp += dzString.charAt((cYear - 4) % 12); // 年支
126. tmp += "年(";
127. //算生肖
128. tmp += sx.charAt((cYear - 4) % 12);
129. tmp += ")";
130. //处理闰月标记之前的闰月,是被处理为负数了
131. if (cMonth < 1) {
132. tmp += "闰";
133. tmp += monString.charAt(-cMonth - 1);
134. } else
135. tmp += monString.charAt(cMonth - 1);
136. tmp += "月";
137. //处理日子
138. tmp += (cDay < 11) ? "初" : ((cDay < 20) ? "十" : ((cDay < 30) ? "廿"
139. : "卅"));
140. if (cDay % 10 != 0 || cDay == 10)
141. tmp += numString.charAt((cDay - 1) % 10);
142. if (cHour == 13)
143. tmp += "夜";
144. //处理时辰
145. tmp += dzString.charAt((cHour - 1) % 12);
146. tmp += "时";
147. return tmp;
148. }
149.
150. //计算两个年份间的闰年数
151. private int countLeapYears(int s, int e) {
152. int count = 0;
153. for (int i = s; i < e; i++) {
154. if (isLeapYear(i)) {
155. count++;
156. }
157. }
158. return count;
159. }
160.
161. //判断年份是否为闰年
162. private boolean isLeapYear(int year) {
163. if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
164. return true;
165. } else {
166. return false;
167. }
168. }
169.
170. public static void main(String[] args) {
171. Lunar lunnar = new Lunar();
172. try {
173. lunnar.e2c("2011年1月20日");
174. } catch (ParseException e) {
175. // TODO Auto-generated catch block
176. e.printStackTrace();
177. }
178. System.out.println(lunnar.getcDateString());
179. }
180.
181. }

相关文档
最新文档