LunarCalender.java
13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
package com.wd.common.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* 中国农历工具类
*
* @author qts
* @data 2023/7/27.
*/
public class LunarCalender {
private int year; // 农历的年份
private int month;
private int day;
private String lunarMonth; // 农历的月份
private boolean leap;
public int leapMonth = 0; // 闰的是哪个月
final static String chineseNumber[] = {"正", "二", "三", "四", "五", "六", "七",
"八", "九", "十", "冬", "腊"};
static SimpleDateFormat chineseDateFormat = new SimpleDateFormat(
"yyyy年MM月dd日");
final static long[] lunarInfo = new long[]{
0x4bd8, 0x4ae0, 0xa570, 0x54d5, 0xd260, 0xd950, 0x5554, 0x56af, 0x9ad0, 0x55d2,
0x4ae0, 0xa5b6, 0xa4d0, 0xd250, 0xd255, 0xb54f, 0xd6a0, 0xada2, 0x95b0, 0x4977,
0x497f, 0xa4b0, 0xb4b5, 0x6a50, 0x6d40, 0xab54, 0x2b6f, 0x9570, 0x52f2, 0x4970,
0x6566, 0xd4a0, 0xea50, 0x6a95, 0x5adf, 0x2b60, 0x86e3, 0x92ef, 0xc8d7, 0xc95f,
0xd4a0, 0xd8a6, 0xb55f, 0x56a0, 0xa5b4, 0x25df, 0x92d0, 0xd2b2, 0xa950, 0xb557,
0x6ca0, 0xb550, 0x5355, 0x4daf, 0xa5b0, 0x4573, 0x52bf, 0xa9a8, 0xe950, 0x6aa0,
0xaea6, 0xab50, 0x4b60, 0xaae4, 0xa570, 0x5260, 0xf263, 0xd950, 0x5b57, 0x56a0,
0x96d0, 0x4dd5, 0x4ad0, 0xa4d0, 0xd4d4, 0xd250, 0xd558, 0xb540, 0xb6a0, 0x95a6,
0x95bf, 0x49b0, 0xa974, 0xa4b0, 0xb27a, 0x6a50, 0x6d40, 0xaf46, 0xab60, 0x9570,
0x4af5, 0x4970, 0x64b0, 0x74a3, 0xea50, 0x6b58, 0x5ac0, 0xab60, 0x96d5, 0x92e0,
0xc960, 0xd954, 0xd4a0, 0xda50, 0x7552, 0x56a0, 0xabb7, 0x25d0, 0x92d0, 0xcab5,
0xa950, 0xb4a0, 0xbaa4, 0xad50, 0x55d9, 0x4ba0, 0xa5b0, 0x5176, 0x52bf, 0xa930,
0x7954, 0x6aa0, 0xad50, 0x5b52, 0x4b60, 0xa6e6, 0xa4e0, 0xd260, 0xea65, 0xd530,
0x5aa0, 0x76a3, 0x96d0, 0x4afb, 0x4ad0, 0xa4d0, 0xd0b6, 0xd25f, 0xd520, 0xdd45,
0xb5a0, 0x56d0, 0x55b2, 0x49b0, 0xa577, 0xa4b0, 0xaa50, 0xb255, 0x6d2f, 0xada0,
0x4b63, 0x937f, 0x49f8, 0x4970, 0x64b0, 0x68a6, 0xea5f, 0x6b20, 0xa6c4, 0xaaef,
0x92e0, 0xd2e3, 0xc960, 0xd557, 0xd4a0, 0xda50, 0x5d55, 0x56a0, 0xa6d0, 0x55d4,
0x52d0, 0xa9b8, 0xa950, 0xb4a0, 0xb6a6, 0xad50, 0x55a0, 0xaba4, 0xa5b0, 0x52b0,
0xb273, 0x6930, 0x7337, 0x6aa0, 0xad50, 0x4b55, 0x4b6f, 0xa570, 0x54e4, 0xd260,
0xe968, 0xd520, 0xdaa0, 0x6aa6, 0x56df, 0x4ae0, 0xa9d4, 0xa4d0, 0xd150, 0xf252,
0xd520};
final static String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊", "己", "庚",
"辛", "壬", "癸"};
final static String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰", "巳", "午",
"未", "申", "酉", "戌", "亥"};
// ====== 传回农历 y年的总天数 1900--2100
public 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年闰月的天数
public int leapDays(int y) {
if (leapMonth(y) != 0) {
if ((lunarInfo[y - 1899] & 0xf) != 0) {
return 30;
} else {
return 29;
}
} else {
return 0;
}
}
// ====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
public int leapMonth(int y) {
long var = lunarInfo[y - 1900] & 0xf;
return (int) (var == 0xf ? 0 : var);
}
// ====== 传回农历 y年m月的总天数
public int monthDays(int y, int m) {
if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) {
return 29;
} else {
return 30;
}
}
// ====== 传回农历 y年的生肖
public String animalsYear(int year) {
final String[] Animals = new String[]{"鼠", "牛", "虎", "兔", "龙", "蛇",
"马", "羊", "猴", "鸡", "狗", "猪"};
return Animals[(year - 4) % 12] + "年";
}
// ====== 传入 月日的offset 传回干支, 0=甲子
final private static String cyclicalm(int num) {
return (Gan[num % 10] + Zhi[num % 12]);
}
// ====== 传入 offset 传回干支, 0=甲子
final public String cyclical(int year, int month, int day) {
int num = year - 1900 + 36;
//立春日期
int term2 = sTerm(year, 2);
if (month > 2 || (month == 2 && day >= term2)) {
num = num + 0;
} else {
num = num - 1;
}
return (cyclicalm(num));
}
public static String getChinaDayString(int day) {//将农历day日格式化成农历表示的字符串
String chineseTen[] = {"初", "十", "廿", "三"};
String chineseDay[] = {"一", "二", "三", "四", "五", "六", "七",
"八", "九", "十"};
String var = "";
if (day != 20 && day != 30) {
var = chineseTen[(int) ((day - 1) / 10)] + chineseDay[(int) ((day - 1) % 10)];
} else if (day != 20) {
var = chineseTen[(int) (day / 10)] + "十";
} else {
var = "二十";
}
return var;
}
/*
* 计算公历nY年nM月nD日和bY年bM月bD日渐相差多少天
* */
public int getDaysOfTwoDate(int bY, int bM, int bD, int nY, int nM, int nD) {
Date baseDate = null;
Date nowaday = null;
try {
baseDate = chineseDateFormat.parse(bY + "年" + bM + "月" + bD + "日");
nowaday = chineseDateFormat.parse(nY + "年" + nM + "月" + nD + "日");
} catch (ParseException e) {
e.printStackTrace();
}
int offset = 0;
if(nowaday != null && baseDate !=null) {
// 求出相差的天数
offset = (int) ((nowaday.getTime() - baseDate.getTime()) / 86400000L);
}
return offset;
}
/*农历lunYear年lunMonth月lunDay日
* isLeap 当前年月是否是闰月
* 从农历日期转换成公历日期
* */
public Calendar getSunDate(int lunYear, int lunMonth, int lunDay, boolean isLeap) {
//公历1900年1月31日为1900年正月初一
int years = lunYear - 1900;
int days = 0;
for (int i = 0; i < years; i++) {
days += yearDays(1900 + i);//农历某年总天数
}
for (int i = 1; i < lunMonth; i++) {
days += monthDays(lunYear, i);
}
if (leapMonth(lunYear) != 0 && lunMonth > leapMonth(lunYear)) {
days += leapDays(lunYear);//lunYear年闰月天数
}
if (isLeap) {
days += monthDays(lunYear, lunMonth);//lunYear年lunMonth月 闰月
}
days += lunDay;
days = days - 1;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1900);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 31);
cal.add(Calendar.DATE, days);
/*
Date date=cal.getTime();
int year_c = cal.get(Calendar.YEAR);
int month_c = cal.get(Calendar.MONTH)+1;
int day_c = cal.get(Calendar.DAY_OF_MONTH);
*/
return cal;
}
public String getLunarString(int year, int month, int day) {
int var = getLunarDateINT(year, month, day);
int lYear = (int) var / 10000;
int lMonth = (int) (var % 10000) / 100;
int lDay = var - lYear * 10000 - lMonth * 100;
String lunY = cyclical(year, month, day) + "年";
String lunM = "";
int testMonth = getSunDate(lYear, lMonth, lDay, false).get(Calendar.MONTH) + 1;
if (testMonth != month) {
lunM = "闰";
}
lunM += chineseNumber[(lMonth - 1) % 12] + "月";
//int leap = leapMonth(lYear);
String lunD = getChinaDayString(lDay);
int animalsYear = 0;
int term2 = sTerm(year, 2);//立春
if (month > 2 || (month == 2 && day >= term2)) {
animalsYear = year;
} else {
animalsYear = year - 1;
}
return lunY + lunM + lunD;
}
/*
* 将公历year年month月day日转换成农历
* 返回格式为20140506(int)
* */
public int getLunarDateINT(int year, int month, int day) {
int iYear, LYear, LMonth, LDay, daysOfYear = 0;
// 求出和1900年1月31日相差的天数
//year =1908;
//month = 3;
//day =3;
int offset = getDaysOfTwoDate(1900, 1, 31, year, month, day);
//Log.i("--ss--","公历:"+year+"-"+month+"-"+day+":"+offset);
// 用offset减去每农历年的天数
// 计算当天是农历第几天
// i最终结果是农历的年份
// offset是当年的第几天
for (iYear = 1900; iYear < 2100 && offset > 0; iYear++) {
daysOfYear = yearDays(iYear);
offset -= daysOfYear;
//Log.i("--ss--","农历:"+iYear+":"+daysOfYear+"/"+offset);
}
if (offset < 0) {
offset += daysOfYear;
iYear--;
//Log.i("--ss--","农历:"+iYear+":"+daysOfYear+"/"+offset);
}
// 农历年份
LYear = iYear;
leapMonth = leapMonth(iYear); // 闰哪个月,1-12
leap = false;
// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
int iMonth = 1, daysOfMonth = 0;
for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
// 闰月
if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) {
--iMonth;
leap = true;
daysOfMonth = leapDays(iYear);
} else {
daysOfMonth = monthDays(iYear, iMonth);
}
// 解除闰月
if (leap && iMonth == (leapMonth + 1)) {
leap = false;
}
offset -= daysOfMonth;
//Log.i("--ss--","农历:"+iYear+"-"+iMonth+":"+daysOfMonth+"/"+offset);
}
// offset为0时,并且刚才计算的月份是闰月,要校正
if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
if (leap) {
leap = false;
} else {
leap = true;
--iMonth;
}
}
// offset小于0时,也要校正
if (offset < 0) {
offset += daysOfMonth;
--iMonth;
//Log.i("--ss--","农历:"+iYear+"-"+iMonth+":"+daysOfMonth+"/"+offset);
}
LMonth = iMonth;
LDay = offset + 1;
//Log.i("--ss--","农历:"+LYear+"-"+LMonth+"-"+LDay);
return LYear * 10000 + LMonth * 100 + LDay;
}
public String toString() {
if (chineseNumber[(month - 1) % 12] == "正" && getChinaDayString(day) == "初一") {
return "农历" + year + "年";
} else if (getChinaDayString(day) == "初一") {
return chineseNumber[(month - 1) % 12] + "月";
} else {
return getChinaDayString(day);
}
// return year + "年" + (leap ? "闰" : "") + chineseNumber[month - 1] +
// "月" + getChinaDayString(day);
}
/*
* public static void main(String[] args) { System.out.println(new
* LunarCalendar().getLunarDate(2012, 1, 23)); }
*/
public int getLeapMonth() {
return leapMonth;
}
public void setLeapMonth(int leapMonth) {
this.leapMonth = leapMonth;
}
/**
* 得到当前日期对应的阴历月份
*
* @return
*/
public String getLunarMonth() {
return lunarMonth;
}
public void setLunarMonth(String lunarMonth) {
this.lunarMonth = lunarMonth;
}
/**
* 得到当前年对应的农历年份
*
* @return
*/
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
private int sTerm(int y, int n) {
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};
Calendar cal = Calendar.getInstance();
cal.set(1900, 0, 6, 2, 5, 0);
long temp = cal.getTime().getTime();
cal.setTime(new Date((long) ((31556925974.7 * (y - 1900) + sTermInfo[n] * 60000L) + temp)));
int a = cal.get(Calendar.DAY_OF_MONTH);
return a;
}
public static String convertToLunarTianGan(int year) {
String[] tianGan = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
int index = (year - 4) % 10;
return tianGan[index];
}
public static String convertToLunarDiZhi(int year) {
String[] diZhi = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
int index = (year - 4) % 12;
return diZhi[index];
}
public static String convertToChineseMonth(int month) {
String[] chineseMonths = {"正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "冬月", "腊月"};
return chineseMonths[month - 1];
}
}