java实现公历转阴历,计算年月日,干支,生肖,节气

时间:2021-02-18 09:47:10
  1 /*
  2  * 创建时间 2004-12-920:32:56
  3  */
  4 package lunarCalendar;
  5 
  6 /**
  7  * @author gcc
  8  *
  9  * TODO
 10  */
 11 
 12 import java.text.ParseException;
 13 import java.text.SimpleDateFormat;
 14 import java.util.Calendar;
 15 import java.util.Date;
 16 
 17 public class LunarCalendar {
 18     private int lyear;
 19     
 20     private int lmonth;
 21     
 22     private int lday;
 23     
 24     private boolean leap;
 25     
 26     private String solarTerms = "";
 27     
 28     private int yearCyl, monCyl, dayCyl;
 29     
 30     private String solarFestival = "";
 31     
 32     private String lunarFestival = "";
 33     
 34     private Calendar baseDate = Calendar.getInstance();
 35     
 36     private Calendar offDate = Calendar.getInstance();
 37     
 38     private SimpleDateFormat chineseDateFormat = new SimpleDateFormat(
 39             "yyyy年MM月dd日");
 40     
 41     final static long[] lunarInfo = new long[] { 0x04bd8, 0x04ae0, 0x0a570,
 42     0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
 43     0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0,
 44     0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50,
 45     0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566,
 46     0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0,
 47     0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4,
 48     0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550,
 49     0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950,
 50     0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,
 51     0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0,
 52     0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
 53     0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40,
 54     0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3,
 55     0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960,
 56     0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0,
 57     0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9,
 58     0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0,
 59     0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65,
 60     0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0,
 61     0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2,
 62     0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 };
 63     
 64     final static String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己",
 65     "庚", "辛", "壬", "癸" };
 66     
 67     final static String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳",
 68     "午", "未", "申", "酉", "戌", "亥" };
 69     
 70     final static String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙",
 71     "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
 72     
 73     final static String[] SolarTerm = new String[] { "小寒", "大寒", "立春", "雨水",
 74     "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋",
 75     "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至" };
 76     
 77     final static long[] STermInfo = new long[] { 0, 21208, 42467, 63836, 85337,
 78     107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343,
 79     285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795,
 80     462224, 483532, 504758 };
 81     
 82     final static String chineseMonthNumber[] = { "正", "二", "三", "四", "五", "六",
 83     "七", "八", "九", "十", "冬", "腊" };
 84     
 85     final static String[] sFtv = new String[] { "0101*元旦", "0214 情人节",
 86     "0308 妇女节", "0312 植树节", "0314 国际警察日", "0315 消费者权益日", "0323 世界气象日",
 87     "0401 愚人节", "0407 世界卫生日", "0501*劳动节", "0504 青年节", "0508 红十字日",
 88     "0512 护士节", "0515 国际家庭日", "0517 世界电信日", "0519 全国助残日", "0531 世界无烟日",
 89     "0601 儿童节", "0605 世界环境日", "0606 全国爱眼日", "0623 奥林匹克日", "0625 全国土地日",
 90     "0626 反毒品日", "0701 建党节", "0707 抗战纪念日", "0711 世界人口日", "0801 建军节",
 91     "0908 国际扫盲日", "0909 毛xx逝世纪念", "0910 教师节", "0917 国际和平日",
 92     "0920 国际爱牙日", "0922 国际聋人节", "0927 世界旅游日", "0928 孔子诞辰", "1001*国庆节",
 93     "1004 世界动物日", "1006 老人节", "1007 国际住房日", "1009 世界邮政日", "1015 国际盲人节",
 94     "1016 世界粮食日", "1024 联合国日", "1031 万圣节", "1108 中国记者日", "1109 消防宣传日",
 95     "1112 孙中山诞辰", "1114 世界糖尿病日", "1117 国际大学生节", "1128 感恩节",
 96     "1201 世界艾滋病日", "1203 世界残疾人日", "1209 世界足球日", "1220 澳门回归",
 97     "1225 圣诞节", "1226 毛xx诞辰" };
 98     
 99     final static String[] lFtv = { "0101*春节", "0115 元宵", "0505 端午",
100     "0707 七夕", "0815 中秋", "0909 重阳", "1208 腊八", "1223 小年",
101     "0100*除夕" };
102     
103     final static String[] wFtv = { "0521 母亲节", "0631 父亲节" };//每年6月第3个星期日是父亲节,5月的第2个星期日是母亲节
104     
105     //星期日是一个周的第1天第3个星期日也就是第3个完整周的第一天
106     
107     //
108     private LunarCalendar() {
109         baseDate.setMinimalDaysInFirstWeek(7);//设置一个月的第一个周是一个完整周
110         
111     }
112     
113     final private static int lYearDays(int y)//====== 传回农历 y年的总天数
114     {
115         int i, sum = 348;
116         for (i = 0x8000; i > 0x8; i >>= 1) {
117             if ((lunarInfo[y - 1900] & i) != 0)
118                 sum += 1;
119         }
120         return (sum + leapDays(y));
121     }
122     
123     final private static int leapDays(int y)//====== 传回农历 y年闰月的天数
124     {
125         if (leapMonth(y) != 0) {
126             if ((lunarInfo[y - 1900] & 0x10000) != 0)
127                 return 30;
128             else
129                 return 29;
130         } else
131             return 0;
132     }
133     
134     final private static int leapMonth(int y)//====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
135     {
136         return (int) (lunarInfo[y - 1900] & 0xf);
137     }
138     
139     final public static int monthDays(int y, int m)//====== 传回农历 y年m月的总天数
140     {
141         if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)
142             return 29;
143         else
144             return 30;
145     }
146     
147     final private static String AnimalsYear(int y)//====== 传回农历 y年的生肖
148     {
149         
150         return Animals[(y - 4) % 12];
151     }
152     
153     final private static String cyclical(int num)//====== 传入 的offset 传回干支,
154     // 0=甲子
155     {
156         
157         return (Gan[num % 10] + Zhi[num % 12]);
158     }
159     
160     //  ===== 某年的第n个节气为几日(从0小寒起算)
161     final private int sTerm(int y, int n) {
162         
163         offDate.set(1900, 0, 6, 2, 5, 0);
164         long temp = offDate.getTime().getTime();
165         offDate
166                 .setTime(new Date(
167                 (long) ((31556925974.7 * (y - 1900) + STermInfo[n] * 60000L) + temp)));
168         
169         return offDate.get(Calendar.DAY_OF_MONTH);
170     }
171     
172     /**
173      * 传出y年m月d日对应的农历.
174      *
175      */
176     private void CalculateLunarCalendar(int y, int m, int d) {
177         
178         int leapMonth = 0;
179         
180         try {
181             baseDate.setTime(chineseDateFormat.parse("1900年1月31日"));
182             
183         } catch (ParseException e) {
184             e.printStackTrace();
185         }
186         long base = baseDate.getTimeInMillis();
187         try {
188             baseDate.setTime(chineseDateFormat.parse(y + "年" + m + "月" + d
189                     + "日"));
190             
191         } catch (ParseException e) {
192             e.printStackTrace();
193         }
194         long obj = baseDate.getTimeInMillis();
195         
196         
197         int offset = (int) ((obj - base) / 86400000L);
198         //System.out.println(offset);
199         //求出和1900年1月31日相差的天数
200         
201         dayCyl = offset + 40;//干支天
202         monCyl = 14;//干支月
203         
204         //用offset减去每农历年的天数
205         // 计算当天是农历第几天
206         //i最终结果是农历的年份
207         //offset是当年的第几天
208         int iYear, daysOfYear = 0;
209         for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) {
210             daysOfYear = lYearDays(iYear);
211             offset -= daysOfYear;
212             monCyl += 12;
213         }
214         if (offset < 0) {
215             offset += daysOfYear;
216             iYear--;
217             monCyl -= 12;
218         }
219         //农历年份
220         lyear = iYear;
221         
222         yearCyl = iYear - 1864;//***********干支年**********//
223         
224         leapMonth = leapMonth(iYear); //闰哪个月,1-12
225         leap = false;
226         
227         //用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
228         int iMonth, daysOfMonth = 0;
229         for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
230             //闰月
231             if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) {
232                 --iMonth;
233                 leap = true;
234                 daysOfMonth = leapDays(iYear);
235             } else
236                 daysOfMonth = monthDays(iYear, iMonth);
237             
238             offset -= daysOfMonth;
239             //解除闰月
240             if (leap && iMonth == (leapMonth + 1))
241                 leap = false;
242             if (!leap)
243                 monCyl++;
244         }
245         //offset为0时,并且刚才计算的月份是闰月,要校正
246         if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
247             if (leap) {
248                 leap = false;
249             } else {
250                 leap = true;
251                 --iMonth;
252                 --monCyl;
253             }
254         }
255         //offset小于0时,也要校正
256         if (offset < 0) {
257             offset += daysOfMonth;
258             --iMonth;
259             --monCyl;
260         }
261         lmonth = iMonth;
262         lday = offset + 1;
263         
264         //******************计算节气**********//
265         
266         if (d == sTerm(y, (m - 1) * 2))
267             solarTerms = SolarTerm[(m - 1) * 2];
268         else if (d == sTerm(y, (m - 1) * 2 + 1))
269             solarTerms = SolarTerm[(m - 1) * 2 + 1];
270         else
271             solarTerms = "";
272         
273         //计算公历节日
274         this.solarFestival = "";
275         for (int i = 0; i < sFtv.length; i++) {
276             if (Integer.parseInt(sFtv[i].substring(0, 2)) == m
277                     && Integer.parseInt(sFtv[i].substring(2, 4)) == d) {
278                 solarFestival = sFtv[i].substring(5);
279             }
280         }
281         //计算农历节日
282         this.lunarFestival = "";
283         for (int i = 0; i < lFtv.length; i++) {
284             if (Integer.parseInt(lFtv[i].substring(0, 2)) == lmonth
285                     && Integer.parseInt(lFtv[i].substring(2, 4)) == lday) {
286                 lunarFestival = lFtv[i].substring(5);
287             }
288         }
289         //计算月周节日
290         
291         // System.out.println(baseDate.get(Calendar.WEEK_OF_MONTH) + ""
292         //       + baseDate.get(Calendar.DAY_OF_WEEK));
293         
294         for (int i = 0; i < wFtv.length; i++) {
295             if (Integer.parseInt(wFtv[i].substring(0, 2)) == m
296                     && Integer.parseInt(wFtv[i].substring(2, 3)) == baseDate
297                     .get(Calendar.WEEK_OF_MONTH)
298                     && Integer.parseInt(wFtv[i].substring(3, 4)) == baseDate
299                     .get(Calendar.DAY_OF_WEEK)) {
300                 solarFestival += wFtv[i].substring(5);
301             }
302         }
303         
304     }
305     
306     //set方法
307     public void set(int y, int m, int d) {
308         
309         CalculateLunarCalendar(y, m, d);
310     }
311     public void set(Calendar cal) {
312         
313         CalculateLunarCalendar(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1,cal.get(Calendar.DAY_OF_MONTH));
314     }
315     //    //get方法组
316     public static LunarCalendar getInstance() {
317         
318         return new LunarCalendar();
319     }
320}