| | |
| | | package org.yeshi.utils;
|
| | |
|
| | | import java.text.ParseException;
|
| | | import java.text.SimpleDateFormat;
|
| | | import java.util.Calendar;
|
| | | import java.util.Date;
|
| | |
|
| | | import javax.script.Invocable;
|
| | | import javax.script.ScriptEngine;
|
| | | import javax.script.ScriptEngineManager;
|
| | |
|
| | | import org.yeshi.utils.entity.DateInfo;
|
| | |
|
| | | /**
|
| | | * 〈将日期转换为干支历法的年月日时,并计算生肖、阴历、星期几〉
|
| | | *
|
| | | */
|
| | | public class DateLunarUtil {
|
| | |
|
| | | static int[] lunarInfo = new int[] { 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, 0x0a5b0, 0x14573,
|
| | | 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950,
|
| | | 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 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, 0x14b63 };
|
| | |
|
| | | static String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };
|
| | | static String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };
|
| | |
|
| | | static long[] sTermInfo = new long[] { 0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551,
|
| | | 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532,
|
| | | 504758 };
|
| | |
|
| | | final static String chineseNumber[] = { "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊" };
|
| | | final static String chineseNumber1[] = { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二" };
|
| | | static SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
|
| | |
|
| | | // 当前年
|
| | | private static Integer year;
|
| | | // 当前月
|
| | | private static Integer month;
|
| | | // 当前日
|
| | | private static Integer day;
|
| | |
|
| | | // 当前星期几
|
| | | private static String weekDay;
|
| | | // 农历-年
|
| | | private static String lunar_year;
|
| | | // 农历-月
|
| | | private static String lunar_month;
|
| | | // 农历-日
|
| | | private static String lunar_day;
|
| | |
|
| | | // 天干地支-年
|
| | | private static String agenary_year;
|
| | | // 天干地支-月
|
| | | private static String agenary_month;
|
| | | // 天干地支-日
|
| | | private static String agenary_day;
|
| | | // 天干地支-时辰
|
| | | private static String agenary_hour;
|
| | |
|
| | | /**
|
| | | * 分裂当前成 年、月、日
|
| | | * |
| | | * @param date
|
| | | */
|
| | | public static void splitDate(Date date) {
|
| | | Calendar cal = Calendar.getInstance();
|
| | | cal.setTime(date);
|
| | | year = cal.get(Calendar.YEAR);
|
| | | month = cal.get(Calendar.MONTH) + 1;
|
| | | day = cal.get(Calendar.DAY_OF_MONTH);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 转换成阴历
|
| | | * |
| | | * @param date
|
| | | * @return
|
| | | */
|
| | | public static String toLunar(Date date) {
|
| | | Calendar cal = Calendar.getInstance();
|
| | | cal.setTime(date);
|
| | |
|
| | | 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);
|
| | |
|
| | | // 用offset减去每农历年的天数
|
| | | // 计算当天是农历第几天
|
| | | // i最终结果是农历的年份
|
| | | // offset是当年的第几天
|
| | | int iYear, daysOfYear = 0;
|
| | | for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) {
|
| | | daysOfYear = lYearDays(iYear);
|
| | | offset -= daysOfYear;
|
| | | }
|
| | | if (offset < 0) {
|
| | | offset += daysOfYear;
|
| | | iYear--;
|
| | | }
|
| | |
|
| | | // 农历年份
|
| | | int year = iYear;
|
| | | leapMonth = leapMonth(iYear); // 闰哪个月,1-12
|
| | |
|
| | | boolean 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;
|
| | | }
|
| | | // 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;
|
| | | }
|
| | |
|
| | | lunar_year = chineseNumberYear(iYear) + "年";
|
| | | if (leap) {
|
| | | lunar_month = "闰" + chineseNumber[iMonth - 1] + "月";
|
| | | } else {
|
| | | lunar_month = chineseNumber[iMonth - 1] + "月";
|
| | | }
|
| | | lunar_day = getChinaDayString(offset + 1);
|
| | | return lunar_year + lunar_month + lunar_day;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 将年份转换为中文
|
| | | * |
| | | * @param year
|
| | | * @return
|
| | | */
|
| | | public static String chineseNumberYear(int year) {
|
| | | String year_str = year + "";
|
| | | String newYear = "";
|
| | | for (int i = 0; i < year_str.length(); i++) {
|
| | | newYear += formatDigit(year_str.charAt(i));
|
| | | }
|
| | | return newYear;
|
| | | }
|
| | |
|
| | | |
| | | public static char formatDigit(char sign) {
|
| | | if (sign == '0')
|
| | | sign = '〇';
|
| | | if (sign == '1')
|
| | | sign = '一';
|
| | | if (sign == '2')
|
| | | sign = '二';
|
| | | if (sign == '3')
|
| | | sign = '三';
|
| | | if (sign == '4')
|
| | | sign = '四';
|
| | | if (sign == '5')
|
| | | sign = '五';
|
| | | if (sign == '6')
|
| | | sign = '六';
|
| | | if (sign == '7')
|
| | | sign = '七';
|
| | | if (sign == '8')
|
| | | sign = '八';
|
| | | if (sign == '9')
|
| | | sign = '九';
|
| | | return sign;
|
| | | }
|
| | |
|
| | | 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 "初十";
|
| | |
|
| | | if (day == 20)
|
| | | return "二十";
|
| | |
|
| | | if (day == 30)
|
| | | return "三十";
|
| | |
|
| | | return chineseTen[day / 10] + chineseNumber1[n];
|
| | | }
|
| | |
|
| | |
|
| | | /**
|
| | | * 计算输出星期几
|
| | | * |
| | | * @param weekday
|
| | | * @return
|
| | | */
|
| | | public static 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 "";
|
| | | }
|
| | |
|
| | | |
| | | /**
|
| | | * 获取星期几中文
|
| | | * |
| | | * @param date
|
| | | * @return
|
| | | */
|
| | | public static String getWeekd(Date date) {
|
| | | Calendar calendar = Calendar.getInstance();
|
| | | calendar.setTime(date);
|
| | | weekDay = "星期" + getChinaWeekdayString(calendar.getTime().toString().substring(0, 3));
|
| | | return weekDay;
|
| | | }
|
| | |
|
| | | |
| | | /**
|
| | | * 返回农历 y年的总天数
|
| | | *
|
| | | * @param y
|
| | | */
|
| | | public static int lYearDays(int y) {
|
| | | int i, sum = 348;
|
| | | for (i = 0x8000; i > 0x8; i >>= 1) {
|
| | | sum += (lunarInfo[y - 1900] & i) > 0 ? 1 : 0;
|
| | | }
|
| | | return (sum + leapDays(y));
|
| | | }
|
| | |
|
| | | |
| | | /**
|
| | | * 返回农历 y年闰月的天数
|
| | | *
|
| | | * @param y
|
| | | * @return
|
| | | */
|
| | | public static int leapDays(int y) {
|
| | | if (leapMonth(y) > 0) {
|
| | | long day = lunarInfo[y - 1900] & 0x10000;
|
| | | return day > 0 ? 30 : 29;
|
| | | } else
|
| | | return 0;
|
| | | }
|
| | | |
| | |
|
| | | /**
|
| | | * 返回农历 y年闰哪个月 1-12 , 没闰返回 0
|
| | | *
|
| | | * @param y
|
| | | * @return
|
| | | */
|
| | | public static int leapMonth(int y) {
|
| | | return (lunarInfo[y - 1900] & 0xf);
|
| | | }
|
| | |
|
| | | |
| | | /**
|
| | | * 返回农历 y年m月的总天数
|
| | | *
|
| | | * @param y
|
| | | * @param m
|
| | | * @return
|
| | | */
|
| | | public static int monthDays(int y, int m) {
|
| | | return ((lunarInfo[y - 1900] & (0x10000 >> m)) > 0 ? 30 : 29);
|
| | | }
|
| | |
|
| | | final public String animalsYear(int year) {
|
| | | final String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
|
| | | return Animals[(year - 4) % 12];
|
| | | }
|
| | |
|
| | | // ===== 某年的第n个节气为几日(从0小寒起算) Date.UTC(1900, 0, 6, 2, 5)
|
| | |
|
| | | /**
|
| | | * 正确的立春时间应该是以小时来进行计算的
|
| | | *
|
| | | * @param y
|
| | | * @param n
|
| | | * @return
|
| | | */
|
| | | public static int sTerm(int y, int n) {
|
| | | long times = 31556925974l * (y - 1900) + sTermInfo[n] * 60000l + (long) 0.7 * (y - 1900);
|
| | | Date offDate = new Date(times - 2208549300000l);
|
| | | // 1、取得本地时间:
|
| | | Calendar cal = Calendar.getInstance();
|
| | | cal.setTime(offDate);
|
| | | // 2、取得时间偏移量:
|
| | | int zoneOffset = cal.get(cal.ZONE_OFFSET);
|
| | | // 3、取得夏令时差:
|
| | | int dstOffset = cal.get(cal.DST_OFFSET);
|
| | | // 4、从本地时间里扣除这些差量,即可以取得UTC时间:
|
| | | cal.add(cal.MILLISECOND, -(zoneOffset + dstOffset));
|
| | | // 之后调用cal.get(int x)或cal.getTimeInMillis()方法所取得的时间即是UTC标准时间。
|
| | | return (cal.get(Calendar.DATE));
|
| | | }
|
| | |
|
| | | /**
|
| | | * 传入 offset 返回干支, 0=甲子
|
| | | *
|
| | | * @param num
|
| | | * @return
|
| | | */
|
| | | public static String cyclical(int num) {
|
| | | return (Gan[num % 10] + Zhi[num % 12]);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 计算 并 打印 八字
|
| | | *
|
| | | * @param date
|
| | | * @throws ParseException
|
| | | */
|
| | | public static String horoscope(Date date) throws ParseException {
|
| | | Calendar cal = Calendar.getInstance();
|
| | | cal.setTime(date);
|
| | |
|
| | | int y = cal.get(Calendar.YEAR);
|
| | | int m = cal.get(Calendar.MONTH);
|
| | | int i = cal.get(Calendar.DATE) - 1;
|
| | |
|
| | | String cY = null;
|
| | | String cM = null;
|
| | | String cD = null;
|
| | | String cH = null;
|
| | |
|
| | | // 年柱 1900年立春后为庚子年(60进制36)
|
| | | if (m < 2) {
|
| | | cY = cyclical(y - 1900 + 36 - 1);
|
| | | } else {
|
| | | cY = cyclical(y - 1900 + 36);
|
| | | }
|
| | | int term2 = sTerm(y, 2); // 立春日期
|
| | | // 月柱 1900年1月小寒以前为 丙子月(60进制12)
|
| | | int firstNode = sTerm(y, m * 2); // 返回当月「节」为几日开始
|
| | | cM = cyclical((y - 1900) * 12 + m + 12);
|
| | | int dayCyclical = jlday(y, m);
|
| | | // 依节气调整二月分的年柱, 以立春为界
|
| | | if (m == 1 && (i + 1) >= term2)
|
| | | cY = cyclical(y - 1900 + 36);
|
| | | // 依节气月柱, 以「节」为界
|
| | | if ((i + 1) >= firstNode)
|
| | | cM = cyclical((y - 1900) * 12 + m + 13);
|
| | | // 日柱
|
| | | cD = cyclical(dayCyclical + i);
|
| | |
|
| | | // 时柱
|
| | | int hour = cal.get(Calendar.HOUR_OF_DAY);
|
| | | cH = Gan[hourG(cD.substring(0, 1), hour)] + Zhi[hourZ(hour)];
|
| | |
|
| | | agenary_year = cY + "年";
|
| | | agenary_month = cM + "月";
|
| | | agenary_day = cD + "日";
|
| | | agenary_hour = cH + "时";
|
| | |
|
| | | return agenary_year + agenary_month + agenary_day + agenary_hour;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 根据 日干 推算 时柱 根据提供的推算图来计算
|
| | | *
|
| | | * @param dG
|
| | | * @param hour
|
| | | * @return
|
| | | */
|
| | | public static int hourG(String dG, int hour) {
|
| | | int ind = 1;
|
| | | for (String s : Gan) {
|
| | | if (s.equals(dG)) {
|
| | | break;
|
| | | }
|
| | | ind++;
|
| | | }
|
| | | ind = ind % 5; // 五个为一周期
|
| | | int hourind = hourZ(hour);
|
| | | if (hourind > 10)
|
| | | return hourind - 10 + (ind - 1) * 2;
|
| | | else {
|
| | | hourind = hourind + (ind - 1) * 2;
|
| | | return hourind >= 10 ? hourind - 10 : hourind;
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * 返回 小时对应的 支的索引
|
| | | *
|
| | | * @param hour
|
| | | * @return
|
| | | */
|
| | | public static int hourZ(int hour) {
|
| | | if (hour >= 23 || hour < 1)
|
| | | return 0;
|
| | | else if (hour >= 1 && hour < 3)
|
| | | return 1;
|
| | | else if (hour >= 3 && hour < 5)
|
| | | return 2;
|
| | | else if (hour >= 5 && hour < 7)
|
| | | return 3;
|
| | | else if (hour >= 7 && hour < 9)
|
| | | return 4;
|
| | | else if (hour >= 9 && hour < 11)
|
| | | return 5;
|
| | | else if (hour >= 11 && hour < 13)
|
| | | return 6;
|
| | | else if (hour >= 13 && hour < 15)
|
| | | return 7;
|
| | | else if (hour >= 15 && hour < 17)
|
| | | return 8;
|
| | | else if (hour >= 17 && hour < 19)
|
| | | return 9;
|
| | | else if (hour >= 19 && hour < 21)
|
| | | return 10;
|
| | | else if (hour >= 21 && hour < 23)
|
| | | return 11;
|
| | | return 0;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 间隔天数
|
| | | *
|
| | | * @param y
|
| | | * @param m
|
| | | * @return
|
| | | */
|
| | | public static int jlday(int y, int m) {
|
| | | ScriptEngineManager sem = new ScriptEngineManager(); /* script引擎管理 */
|
| | | ScriptEngine se = sem.getEngineByName("javascript"); /* script引擎 */
|
| | | try {
|
| | | se.eval(" var y =" + y + ",m=" + m + " ;"); /* 执行一段script */
|
| | | se.eval("function jlday( ) { " + "return Date.UTC(y,m,1,0,0,0,0)/86400000+25567+10;" + "}"); /* 添加一个方法 */
|
| | | Invocable invocableEngine = (Invocable) se;
|
| | | Object callbackvalue = invocableEngine.invokeFunction("jlday"); /* 调用方法中的函数 */
|
| | | if (callbackvalue != null) {
|
| | | double numdb = Double.valueOf(callbackvalue.toString());
|
| | | return (int) numdb;
|
| | | }
|
| | | } catch (Exception e) {
|
| | | e.printStackTrace();
|
| | | }
|
| | | return 0;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 获取日期信息
|
| | | * |
| | | * @param date
|
| | | * @return
|
| | | * @throws ParseException
|
| | | */
|
| | | public static DateInfo getDateInfo(Date date) throws ParseException {
|
| | |
|
| | | DateInfo dateInfo = new DateInfo();
|
| | | // 分裂成年、月、日
|
| | | splitDate(date);
|
| | | dateInfo.setDay(day);
|
| | | dateInfo.setMonth(month);
|
| | | dateInfo.setYear(year);
|
| | |
|
| | | // 星期几
|
| | | getWeekd(date);
|
| | | dateInfo.setWeekDay(weekDay);
|
| | |
|
| | | // 转换成农历日期
|
| | | toLunar(date);
|
| | | dateInfo.setLunar_year(lunar_year);
|
| | | dateInfo.setLunar_month(lunar_month);
|
| | | dateInfo.setLunar_day(lunar_day);
|
| | |
|
| | | // 天干地支
|
| | | horoscope(date);
|
| | | dateInfo.setAgenary_year(agenary_year);
|
| | | dateInfo.setAgenary_month(agenary_month);
|
| | | dateInfo.setAgenary_day(agenary_day);
|
| | | dateInfo.setAgenary_hour(agenary_hour);
|
| | |
|
| | | return dateInfo;
|
| | | }
|
| | |
|
| | | public static void main(String[] args) throws ParseException {
|
| | | Date date = new Date();
|
| | |
|
| | | String lunar = DateLunarUtil.toLunar(date);
|
| | | System.out.println(lunar);
|
| | |
|
| | | String horoscope = DateLunarUtil.horoscope(date);
|
| | | System.out.println(horoscope);
|
| | |
|
| | | System.out.println(getWeekd(date));
|
| | |
|
| | | }
|
| | |
|
| | | package org.yeshi.utils; |
| | | |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Calendar; |
| | | import java.util.Date; |
| | | |
| | | import javax.script.Invocable; |
| | | import javax.script.ScriptEngine; |
| | | import javax.script.ScriptEngineManager; |
| | | |
| | | import org.yeshi.utils.entity.DateInfo; |
| | | |
| | | /** |
| | | * 〈将日期转换为干支历法的年月日时,并计算生肖、阴历、星期几〉 |
| | | * |
| | | */ |
| | | public class DateLunarUtil { |
| | | |
| | | static int[] lunarInfo = new int[] { 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, 0x0a5b0, 0x14573, |
| | | 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, |
| | | 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 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, 0x14b63 }; |
| | | |
| | | static String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" }; |
| | | static String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" }; |
| | | |
| | | static long[] sTermInfo = new long[] { 0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, |
| | | 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, |
| | | 504758 }; |
| | | |
| | | final static String chineseNumber[] = { "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "腊" }; |
| | | final static String chineseNumber1[] = { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二" }; |
| | | static SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy年MM月dd日"); |
| | | |
| | | // 当前年 |
| | | private static Integer year; |
| | | // 当前月 |
| | | private static Integer month; |
| | | // 当前日 |
| | | private static Integer day; |
| | | |
| | | // 当前星期几 |
| | | private static String weekDay; |
| | | // 农历-年 |
| | | private static String lunar_year; |
| | | // 农历-月 |
| | | private static String lunar_month; |
| | | // 农历-日 |
| | | private static String lunar_day; |
| | | |
| | | // 天干地支-年 |
| | | private static String agenary_year; |
| | | // 天干地支-月 |
| | | private static String agenary_month; |
| | | // 天干地支-日 |
| | | private static String agenary_day; |
| | | // 天干地支-时辰 |
| | | private static String agenary_hour; |
| | | |
| | | /** |
| | | * 分裂当前成 年、月、日 |
| | | * |
| | | * @param date |
| | | */ |
| | | public static void splitDate(Date date) { |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(date); |
| | | year = cal.get(Calendar.YEAR); |
| | | month = cal.get(Calendar.MONTH) + 1; |
| | | day = cal.get(Calendar.DAY_OF_MONTH); |
| | | } |
| | | |
| | | /** |
| | | * 转换成阴历 |
| | | * |
| | | * @param date |
| | | * @return |
| | | */ |
| | | public static String toLunar(Date date) { |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(date); |
| | | |
| | | 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); |
| | | |
| | | // 用offset减去每农历年的天数 |
| | | // 计算当天是农历第几天 |
| | | // i最终结果是农历的年份 |
| | | // offset是当年的第几天 |
| | | int iYear, daysOfYear = 0; |
| | | for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) { |
| | | daysOfYear = lYearDays(iYear); |
| | | offset -= daysOfYear; |
| | | } |
| | | if (offset < 0) { |
| | | offset += daysOfYear; |
| | | iYear--; |
| | | } |
| | | |
| | | // 农历年份 |
| | | int year = iYear; |
| | | leapMonth = leapMonth(iYear); // 闰哪个月,1-12 |
| | | |
| | | boolean 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; |
| | | } |
| | | // 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; |
| | | } |
| | | |
| | | lunar_year = chineseNumberYear(iYear) + "年"; |
| | | if (leap) { |
| | | lunar_month = "闰" + chineseNumber[iMonth - 1] + "月"; |
| | | } else { |
| | | lunar_month = chineseNumber[iMonth - 1] + "月"; |
| | | } |
| | | lunar_day = getChinaDayString(offset + 1); |
| | | return lunar_year + lunar_month + lunar_day; |
| | | } |
| | | |
| | | /** |
| | | * 将年份转换为中文 |
| | | * |
| | | * @param year |
| | | * @return |
| | | */ |
| | | public static String chineseNumberYear(int year) { |
| | | String year_str = year + ""; |
| | | String newYear = ""; |
| | | for (int i = 0; i < year_str.length(); i++) { |
| | | newYear += formatDigit(year_str.charAt(i)); |
| | | } |
| | | return newYear; |
| | | } |
| | | |
| | | |
| | | public static char formatDigit(char sign) { |
| | | if (sign == '0') |
| | | sign = '〇'; |
| | | if (sign == '1') |
| | | sign = '一'; |
| | | if (sign == '2') |
| | | sign = '二'; |
| | | if (sign == '3') |
| | | sign = '三'; |
| | | if (sign == '4') |
| | | sign = '四'; |
| | | if (sign == '5') |
| | | sign = '五'; |
| | | if (sign == '6') |
| | | sign = '六'; |
| | | if (sign == '7') |
| | | sign = '七'; |
| | | if (sign == '8') |
| | | sign = '八'; |
| | | if (sign == '9') |
| | | sign = '九'; |
| | | return sign; |
| | | } |
| | | |
| | | 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 "初十"; |
| | | |
| | | if (day == 20) |
| | | return "二十"; |
| | | |
| | | if (day == 30) |
| | | return "三十"; |
| | | |
| | | return chineseTen[day / 10] + chineseNumber1[n]; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 计算输出星期几 |
| | | * |
| | | * @param weekday |
| | | * @return |
| | | */ |
| | | public static 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 ""; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取星期几中文 |
| | | * |
| | | * @param date |
| | | * @return |
| | | */ |
| | | public static String getWeekd(Date date) { |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.setTime(date); |
| | | weekDay = "星期" + getChinaWeekdayString(calendar.getTime().toString().substring(0, 3)); |
| | | return weekDay; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 返回农历 y年的总天数 |
| | | * |
| | | * @param y |
| | | */ |
| | | public static int lYearDays(int y) { |
| | | int i, sum = 348; |
| | | for (i = 0x8000; i > 0x8; i >>= 1) { |
| | | sum += (lunarInfo[y - 1900] & i) > 0 ? 1 : 0; |
| | | } |
| | | return (sum + leapDays(y)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 返回农历 y年闰月的天数 |
| | | * |
| | | * @param y |
| | | * @return |
| | | */ |
| | | public static int leapDays(int y) { |
| | | if (leapMonth(y) > 0) { |
| | | long day = lunarInfo[y - 1900] & 0x10000; |
| | | return day > 0 ? 30 : 29; |
| | | } else |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 返回农历 y年闰哪个月 1-12 , 没闰返回 0 |
| | | * |
| | | * @param y |
| | | * @return |
| | | */ |
| | | public static int leapMonth(int y) { |
| | | return (lunarInfo[y - 1900] & 0xf); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 返回农历 y年m月的总天数 |
| | | * |
| | | * @param y |
| | | * @param m |
| | | * @return |
| | | */ |
| | | public static int monthDays(int y, int m) { |
| | | return ((lunarInfo[y - 1900] & (0x10000 >> m)) > 0 ? 30 : 29); |
| | | } |
| | | |
| | | final public String animalsYear(int year) { |
| | | final String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" }; |
| | | return Animals[(year - 4) % 12]; |
| | | } |
| | | |
| | | // ===== 某年的第n个节气为几日(从0小寒起算) Date.UTC(1900, 0, 6, 2, 5) |
| | | |
| | | /** |
| | | * 正确的立春时间应该是以小时来进行计算的 |
| | | * |
| | | * @param y |
| | | * @param n |
| | | * @return |
| | | */ |
| | | public static int sTerm(int y, int n) { |
| | | long times = 31556925974l * (y - 1900) + sTermInfo[n] * 60000l + (long) 0.7 * (y - 1900); |
| | | Date offDate = new Date(times - 2208549300000l); |
| | | // 1、取得本地时间: |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(offDate); |
| | | // 2、取得时间偏移量: |
| | | int zoneOffset = cal.get(cal.ZONE_OFFSET); |
| | | // 3、取得夏令时差: |
| | | int dstOffset = cal.get(cal.DST_OFFSET); |
| | | // 4、从本地时间里扣除这些差量,即可以取得UTC时间: |
| | | cal.add(cal.MILLISECOND, -(zoneOffset + dstOffset)); |
| | | // 之后调用cal.get(int x)或cal.getTimeInMillis()方法所取得的时间即是UTC标准时间。 |
| | | return (cal.get(Calendar.DATE)); |
| | | } |
| | | |
| | | /** |
| | | * 传入 offset 返回干支, 0=甲子 |
| | | * |
| | | * @param num |
| | | * @return |
| | | */ |
| | | public static String cyclical(int num) { |
| | | return (Gan[num % 10] + Zhi[num % 12]); |
| | | } |
| | | |
| | | /** |
| | | * 计算 并 打印 八字 |
| | | * |
| | | * @param date |
| | | * @throws ParseException |
| | | */ |
| | | public static String horoscope(Date date) throws ParseException { |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(date); |
| | | |
| | | int y = cal.get(Calendar.YEAR); |
| | | int m = cal.get(Calendar.MONTH); |
| | | int i = cal.get(Calendar.DATE) - 1; |
| | | |
| | | String cY = null; |
| | | String cM = null; |
| | | String cD = null; |
| | | String cH = null; |
| | | |
| | | // 年柱 1900年立春后为庚子年(60进制36) |
| | | if (m < 2) { |
| | | cY = cyclical(y - 1900 + 36 - 1); |
| | | } else { |
| | | cY = cyclical(y - 1900 + 36); |
| | | } |
| | | int term2 = sTerm(y, 2); // 立春日期 |
| | | // 月柱 1900年1月小寒以前为 丙子月(60进制12) |
| | | int firstNode = sTerm(y, m * 2); // 返回当月「节」为几日开始 |
| | | cM = cyclical((y - 1900) * 12 + m + 12); |
| | | int dayCyclical = jlday(y, m); |
| | | // 依节气调整二月分的年柱, 以立春为界 |
| | | if (m == 1 && (i + 1) >= term2) |
| | | cY = cyclical(y - 1900 + 36); |
| | | // 依节气月柱, 以「节」为界 |
| | | if ((i + 1) >= firstNode) |
| | | cM = cyclical((y - 1900) * 12 + m + 13); |
| | | // 日柱 |
| | | cD = cyclical(dayCyclical + i); |
| | | |
| | | // 时柱 |
| | | int hour = cal.get(Calendar.HOUR_OF_DAY); |
| | | cH = Gan[hourG(cD.substring(0, 1), hour)] + Zhi[hourZ(hour)]; |
| | | |
| | | agenary_year = cY + "年"; |
| | | agenary_month = cM + "月"; |
| | | agenary_day = cD + "日"; |
| | | agenary_hour = cH + "时"; |
| | | |
| | | return agenary_year + agenary_month + agenary_day + agenary_hour; |
| | | } |
| | | |
| | | /** |
| | | * 根据 日干 推算 时柱 根据提供的推算图来计算 |
| | | * |
| | | * @param dG |
| | | * @param hour |
| | | * @return |
| | | */ |
| | | public static int hourG(String dG, int hour) { |
| | | int ind = 1; |
| | | for (String s : Gan) { |
| | | if (s.equals(dG)) { |
| | | break; |
| | | } |
| | | ind++; |
| | | } |
| | | ind = ind % 5; // 五个为一周期 |
| | | int hourind = hourZ(hour); |
| | | if (hourind > 10) |
| | | return hourind - 10 + (ind - 1) * 2; |
| | | else { |
| | | hourind = hourind + (ind - 1) * 2; |
| | | return hourind >= 10 ? hourind - 10 : hourind; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 返回 小时对应的 支的索引 |
| | | * |
| | | * @param hour |
| | | * @return |
| | | */ |
| | | public static int hourZ(int hour) { |
| | | if (hour >= 23 || hour < 1) |
| | | return 0; |
| | | else if (hour >= 1 && hour < 3) |
| | | return 1; |
| | | else if (hour >= 3 && hour < 5) |
| | | return 2; |
| | | else if (hour >= 5 && hour < 7) |
| | | return 3; |
| | | else if (hour >= 7 && hour < 9) |
| | | return 4; |
| | | else if (hour >= 9 && hour < 11) |
| | | return 5; |
| | | else if (hour >= 11 && hour < 13) |
| | | return 6; |
| | | else if (hour >= 13 && hour < 15) |
| | | return 7; |
| | | else if (hour >= 15 && hour < 17) |
| | | return 8; |
| | | else if (hour >= 17 && hour < 19) |
| | | return 9; |
| | | else if (hour >= 19 && hour < 21) |
| | | return 10; |
| | | else if (hour >= 21 && hour < 23) |
| | | return 11; |
| | | return 0; |
| | | } |
| | | |
| | | /** |
| | | * 间隔天数 |
| | | * |
| | | * @param y |
| | | * @param m |
| | | * @return |
| | | */ |
| | | public static int jlday(int y, int m) { |
| | | ScriptEngineManager sem = new ScriptEngineManager(); /* script引擎管理 */ |
| | | ScriptEngine se = sem.getEngineByName("javascript"); /* script引擎 */ |
| | | try { |
| | | se.eval(" var y =" + y + ",m=" + m + " ;"); /* 执行一段script */ |
| | | se.eval("function jlday( ) { " + "return Date.UTC(y,m,1,0,0,0,0)/86400000+25567+10;" + "}"); /* 添加一个方法 */ |
| | | Invocable invocableEngine = (Invocable) se; |
| | | Object callbackvalue = invocableEngine.invokeFunction("jlday"); /* 调用方法中的函数 */ |
| | | if (callbackvalue != null) { |
| | | double numdb = Double.valueOf(callbackvalue.toString()); |
| | | return (int) numdb; |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | /** |
| | | * 获取日期信息 |
| | | * |
| | | * @param date |
| | | * @return |
| | | * @throws ParseException |
| | | */ |
| | | public static DateInfo getDateInfo(Date date) throws ParseException { |
| | | |
| | | DateInfo dateInfo = new DateInfo(); |
| | | // 分裂成年、月、日 |
| | | splitDate(date); |
| | | dateInfo.setDay(day); |
| | | dateInfo.setMonth(month); |
| | | dateInfo.setYear(year); |
| | | |
| | | // 星期几 |
| | | getWeekd(date); |
| | | dateInfo.setWeekDay(weekDay); |
| | | |
| | | // 转换成农历日期 |
| | | toLunar(date); |
| | | dateInfo.setLunar_year(lunar_year); |
| | | dateInfo.setLunar_month(lunar_month); |
| | | dateInfo.setLunar_day(lunar_day); |
| | | |
| | | // 天干地支 |
| | | horoscope(date); |
| | | dateInfo.setAgenary_year(agenary_year); |
| | | dateInfo.setAgenary_month(agenary_month); |
| | | dateInfo.setAgenary_day(agenary_day); |
| | | dateInfo.setAgenary_hour(agenary_hour); |
| | | |
| | | return dateInfo; |
| | | } |
| | | |
| | | public static void main(String[] args) throws ParseException { |
| | | Date date = new Date(); |
| | | |
| | | String lunar = DateLunarUtil.toLunar(date); |
| | | System.out.println(lunar); |
| | | |
| | | String horoscope = DateLunarUtil.horoscope(date); |
| | | System.out.println(horoscope); |
| | | |
| | | System.out.println(getWeekd(date)); |
| | | |
| | | } |
| | | |
| | | } |