现在的位置: 首页 > 综合 > 正文

java版本的八字计算

2013年06月19日 ⁄ 综合 ⁄ 共 9777字 ⁄ 字号 评论关闭

 看了网上不少的例子,整理一个能计算1900年以后的八字计算程序。同时能获取生肖以及阴历生日

 

  1. package com.knight.cal;
  2. import java.text.ParseException;
  3. import java.text.SimpleDateFormat;
  4. import java.util.Calendar;
  5. import java.util.Date;
  6. /**
  7.  * 根据西元的生日时辰获取某个人的生辰八字,以及农历生日
  8.  *@author kongqz 
  9.  * */
  10. public class BaZi {
  11.     private int year;
  12.     private int month;
  13.     private int day;
  14.     private boolean leap;
  15.     Date baseDate = null;
  16.     final static String chineseNumber[] = {"正""二""三""四""五""六""七""八""九""十""十一""腊"};
  17.     final static String[] Gan = {"甲""乙""丙""丁""戊""己""庚""辛""壬""癸"};
  18.     final static String[] Zhi = {"子""丑""寅""卯""辰""巳""午""未""申""酉""戌""亥"};
  19.     static SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  20.     final static long[] lunarInfo = new long[]{0x04bd80x04ae00x0a5700x054d50x0d2600x0d9500x165540x056a00x09ad00x055d2,
  21.         0x04ae00x0a5b60x0a4d00x0d2500x1d2550x0b5400x0d6a00x0ada20x095b00x14977,
  22.         0x049700x0a4b00x0b4b50x06a500x06d400x1ab540x02b600x095700x052f20x04970,
  23.         0x065660x0d4a00x0ea500x06e950x05ad00x02b600x186e30x092e00x1c8d70x0c950,
  24.         0x0d4a00x1d8a60x0b5500x056a00x1a5b40x025d00x092d00x0d2b20x0a9500x0b557,
  25.         0x06ca00x0b5500x153550x04da00x0a5d00x145730x052d00x0a9a80x0e9500x06aa0,
  26.         0x0aea60x0ab500x04b600x0aae40x0a5700x052600x0f2630x0d9500x05b570x056a0,
  27.         0x096d00x04dd50x04ad00x0a4d00x0d4d40x0d2500x0d5580x0b5400x0b5a00x195a6,
  28.         0x095b00x049b00x0a9740x0a4b00x0b27a0x06a500x06d400x0af460x0ab600x09570,
  29.         0x04af50x049700x064b00x074a30x0ea500x06b580x055c00x0ab600x096d50x092e0,
  30.         0x0c9600x0d9540x0d4a00x0da500x075520x056a00x0abb70x025d00x092d00x0cab5,
  31.         0x0a9500x0b4a00x0baa40x0ad500x055d90x04ba00x0a5b00x151760x052b00x0a930,
  32.         0x079540x06aa00x0ad500x05b520x04b600x0a6e60x0a4e00x0d2600x0ea650x0d530,
  33.         0x05aa00x076a30x096d00x04bd70x04ad00x0a4d00x1d0b60x0d2500x0d5200x0dd45,
  34.         0x0b5a00x056d00x055b20x049b00x0a5770x0a4b00x0aa500x1b2550x06d200x0ada0
  35.     };
  36.     /**
  37.      * 六十甲子
  38.      */
  39.     public static final String[] jiazhi = {
  40.         "甲子""乙丑""丙寅""丁卯""戊辰""己巳""庚午""辛未""壬申""癸酉",
  41.         "甲戌""乙亥""丙子""丁丑""戊寅""己卯""庚辰""辛巳""壬午""癸未",
  42.         "甲申""乙酉""丙戌""丁亥""戊子""己丑""庚寅""辛卯""壬辰""癸巳",
  43.         "甲午""乙未""丙申""丁酉""戊戌""己亥""庚子""辛丑""壬寅""癸卯",
  44.         "甲辰""乙巳""丙午""丁未""戊申""己酉""庚戌""辛亥""壬子""癸丑",
  45.         "甲寅""乙卯""丙辰""丁巳""戊午""己未""庚申""辛酉""壬戌""癸亥"
  46.     };
  47.     private Calendar cal;
  48.     /**
  49.      * @param hour 这里的时间范围是1-12,具体几点到几点是子时、丑时请参考相关文档
  50.      * 具体的选择如下 "子:1", "丑:2", "寅:3", "卯:4", "辰:5", "巳:6", "午:7", "未:8", "申:9", "酉:10", "戌:11", "亥:12" 
  51.      * @author kongqz
  52.      * */
  53.     public String getYearGanZhi(int hour) {
  54.         //1864年是甲子年,每隔六十年一个甲子
  55.         int idx = (year - 1864) % 60;
  56.         //没有过春节的话那么年还算上一年的,此处求的年份的干支
  57.         String y = jiazhi[idx];
  58.         
  59.         String m="";
  60.         String d="";
  61.         String h="";
  62.         idx = idx % 5;
  63.         int idxm=0;
  64.         /**
  65.          * 年上起月
  66.          * 甲己之年丙作首,乙庚之岁戊为头,
  67.          * 丙辛必定寻庚起,丁壬壬位顺行流,
  68.          * 更有戊癸何方觅,甲寅之上好追求。
  69.          */
  70.         idxm=(idx+1)*2;
  71.         if(idxm==10) idxm=0;
  72.         //求的月份的干支
  73.         m=Gan[(idxm+month-1)%10]+Zhi[(month+2-1)%12];
  74.        
  75.         
  76.         /*求出和1900年1月31日甲辰日相差的天数 
  77.          * 甲辰日是第四十天
  78.         */
  79.         int offset = (int) ((cal.getTime().getTime() - baseDate.getTime()) / 86400000L);
  80.         offset=(offset+40)%60;
  81.         //求的日的干支
  82.         d=jiazhi[offset];
  83.         
  84.         /**
  85.          * 日上起时
  86.          * 甲己还生甲,乙庚丙作初,
  87.          * 丙辛从戊起,丁壬庚子居,
  88.          * 戊癸何方发,壬子是真途。  
  89.          */ 
  90.         
  91.         offset=(offset % 5 )*2;
  92.         //求得时辰的干支   
  93.         h=Gan[(offset+hour-1)%10]+Zhi[hour-1];
  94.         //在此处输出我们的年月日时的天干地支
  95.         return y+m+d+h;
  96.     }
  97.     public String getShichenFromDay(int offset){
  98.        
  99.         return null;
  100.     }
  101. //====== 传回农历 y年的总天数
  102.     final private static int yearDays(int y) {
  103.         int i,  sum = 348;
  104.         for (i = 0x8000; i > 0x8; i >>= 1) {
  105.             if ((lunarInfo[y - 1900] & i) != 0) {
  106.                 sum += 1;
  107.             }
  108.         }
  109.         return (sum + leapDays(y));
  110.     }
  111. //====== 传回农历 y年闰月的天数
  112.     final private static int leapDays(int y) {
  113.         if (leapMonth(y) != 0) {
  114.             if ((lunarInfo[y - 1900] & 0x10000) != 0) {
  115.                 return 30;
  116.             } else {
  117.                 return 29;
  118.             }
  119.         } else {
  120.             return 0;
  121.         }
  122.     }
  123. //====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
  124.     final private static int leapMonth(int y) {
  125.         return (int) (lunarInfo[y - 1900] & 0xf);
  126.     }
  127. //====== 传回农历 y年m月的总天数
  128.     final private static int monthDays(int y, int m) {
  129.         if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) {
  130.             return 29;
  131.         } else {
  132.             return 30;
  133.         }
  134.     }
  135. /*** 
  136.  * @return 传回农历 y年的生肖
  137.  */
  138.     final public String animalsYear() {
  139.         final String[] Animals = new String[]{"鼠""牛""虎""兔""龙""蛇""马""羊""猴""鸡""狗""猪"};
  140.         return Animals[(year - 4) % 12];
  141.     }
  142. //====== 传入 月日的offset 传回干支, 0=甲子
  143.     final private static String cyclicalm(int num) {
  144.         return (Gan[num % 10] + Zhi[num % 12]);
  145.     }
  146. //====== 传入 offset 传回干支, 0=甲子
  147.     final public String cyclical() {
  148.         int num = year - 1900 + 36;
  149.         return (cyclicalm(num));
  150.     }
  151.     /**
  152.      * 传出y年m月d日对应的农历.
  153.      * yearCyl3:农历年与1864的相差数 ?
  154.      * monCyl4:从1900年1月31日以来,闰月数
  155.      * dayCyl5:与1900年1月31日相差的天数,再加40 ?
  156.      *
  157.      * @param cal
  158.      * @return
  159.      */
  160.     public BaZi(Calendar cal) {
  161.         this.cal=cal;
  162.         int yearCyl,  monCyl,  dayCyl;
  163.         int leapMonth = 0;
  164.         
  165.         try {
  166.             baseDate = chineseDateFormat.parse("1900-1-31");
  167.         } catch (ParseException e) {
  168.             e.printStackTrace(); //To change body of catch statement use Options | File Templates.
  169.         }
  170. //求出和1900年1月31日相差的天数
  171.         int offset = (int) ((cal.getTime().getTime() - baseDate.getTime()) / 86400000L);
  172.         dayCyl = offset + 40;
  173.         monCyl = 14;
  174. //用offset减去每农历年的天数
  175. // 计算当天是农历第几天
  176. //i最终结果是农历的年份
  177. //offset是当年的第几天
  178.         int iYear,  daysOfYear = 0;
  179.         for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) {
  180.             daysOfYear = yearDays(iYear);
  181.             offset -= daysOfYear;
  182.             monCyl += 12;
  183.         }
  184.         if (offset < 0) {
  185.             offset += daysOfYear;
  186.             iYear--;
  187.             monCyl -= 12;
  188.         }
  189. //农历年份
  190.         year = iYear;
  191.         yearCyl = iYear - 1864;
  192.         leapMonth = leapMonth(iYear); //闰哪个月,1-12
  193.         leap = false;
  194. //用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
  195.         int iMonth,  daysOfMonth = 0;
  196.         for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
  197. //闰月
  198.             if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) {
  199.                 --iMonth;
  200.                 leap = true;
  201.                 daysOfMonth = leapDays(year);
  202.             } else {
  203.                 daysOfMonth = monthDays(year, iMonth);
  204.             }
  205.             offset -= daysOfMonth;
  206. //解除闰月
  207.             if (leap && iMonth == (leapMonth + 1)) {
  208.                 leap = false;
  209.             }
  210.             if (!leap) {
  211.                 monCyl++;
  212.             }
  213.         }
  214. //offset为0时,并且刚才计算的月份是闰月,要校正
  215.         if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
  216.             if (leap) {
  217.                 leap = false;
  218.             } else {
  219.                 leap = true;
  220.                 --iMonth;
  221.                 --monCyl;
  222.             }
  223.         }
  224. //offset小于0时,也要校正
  225.         if (offset < 0) {
  226.             offset += daysOfMonth;
  227.             --iMonth;
  228.             --monCyl;
  229.         }
  230.         month = iMonth;
  231.         day = offset + 1;
  232.     }
  233.     public static String getChinaDayString(int day) {
  234.         String chineseTen[] = {"初""十""廿""卅"};
  235.         int n = day % 10 == 0 ? 9 : day % 10 - 1;
  236.         if (day > 30) {
  237.             return "";
  238.         }
  239.         if (day == 10) {
  240.             return "初十";
  241.         } else {
  242.             return chineseTen[day / 10] + chineseNumber[n];
  243.         }
  244.     }
  245.     public String toString() {
  246.         return getYearStr(year) + "年" + (leap ? "闰" : "") + chineseNumber[month - 1] + "月" + getChinaDayString(day);
  247.     }
  248.     public String getYearStr(int year) {
  249.         String[] chineseword = {"零""一""二""三""四""五""六""七""八""九"};
  250.         String ys = "";
  251.         int index = year / 1000;
  252.         ys += chineseword[index];
  253.         year = year % 1000;
  254.         index = year / 100;
  255.         ys += chineseword[index];
  256.         year = year % 100;
  257.         index = year / 10;
  258.         ys += chineseword[index];
  259.         year = year % 10;
  260.         index = year;
  261.         ys += chineseword[index];
  262.         return ys;
  263.     }
  264.     public static String getSixtyDay() {
  265.         String temp = "";
  266.         for (int i = 0; i < 60; i++) {
  267.             temp += ",/"" + cyclicalm(i) + "/"";
  268.         }
  269.         return temp;
  270.     }
  271.     
  272.     /**
  273.      * 针对一个在西元 1983-01-10 中午12:30生的人的计算。
  274.      * 这里12点半在中国的古代历书中算是午时
  275.      * 子时23.00-1.00,丑时1.00-3.00,寅时3.00-5.00,卯时5.00-7.00,
  276.      * 辰时7.00-9.00,巳时9.00-11.00,午时11.00-13.00,未时13.00-15.00
  277.      * 申时15.00-17.00,酉时17.00-19.00,戌时19.00-21.00,亥时21.00-23.00
  278.      * */
  279.     public static void main(String[] args){
  280.         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  281.         Calendar cal = Calendar.getInstance();
  282.         try {
  283.                 //设定此人的西元时间为1983-01-10
  284.                 cal.setTime(sdf.parse("1983-01-10"));
  285.                 BaZi lunar = new BaZi(cal);
  286.                 System.out.println("此人农历的日期【"+lunar.toString()+"】");
  287.                 //此处是为了获取时间在中国的八字学说上的显示,此人是午时生的
  288.                 System.out.println("此人八字【"+lunar.getYearGanZhi(7)+"】");
  289.                 //获取生肖
  290.                 System.out.println("此人的农历生肖【"+lunar.animalsYear()+"】");
  291.         }catch(Exception e){
  292.             e.printStackTrace();
  293.         }
  294.     }
  295. }

 

如果有更好的版本,能计算前后节气的,一起拿出来共享吧:)

【上篇】
【下篇】

抱歉!评论已关闭.