獲得陰陽曆 年月日時

package com.huawei.test;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class Lunar2 {
private Calendar solar;
private int lunarYear;
private int lunarMonth;
private int lunarDay;
private boolean isLeapYear;
private boolean isLeap;
private int maxDayInMonth = 29;
private final static int[] lunarInfo = {
0x4bd8, 0x4ae0, 0xa570, 0x54d5, 0xd260, 0xd950, 0x5554, 0x56af,
0x9ad0, 0x55d2, 0x4ae0, 0xa5b6, 0xa4d0, 0xd250, 0xd295, 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
};

private int solarYear;  
private int solarMonth;  
private int solarDay;  
private int cyclicalYear = 0;  
private int cyclicalMonth = 0;  
private int cyclicalDay = 0;  

private final static int[] solarTermInfo = {  
    0, 21208, 42467, 63836, 85337, 107014, 128867, 150921,  
    173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033,  
    353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758  
}; 

private static GregorianCalendar utcCal = null;  

public final static String[] Tianan = {  
    "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"  
};  
public final static String[] Deqi = {  
    "子", "醜", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"  
};
//總方法
public static void main(String args[]) throws ParseException {
    DateFormat fmt =new SimpleDateFormat("yyyy-MM-dd");
    Date date = fmt.parse("1990-08-20");
    Lunar2 l = new Lunar2(date);  
   // System.out.println("節氣:" + l.getTermString());  
    System.out.println("干支歷:" + l.getCyclicalDateString());  
}
 /** 
 * 通過 Date 對象構建農曆信息 
 * 
 * @param date 指定日期對象 
 */  
public Lunar2(Date date) {  
    if (date == null) {  
        date = new Date();  
    }  
    this.init(date.getTime());  
}  
/** 
 * 通過 TimeInMillis 構建農曆信息 
 * 
 * @param TimeInMillis 
 */  
public Lunar2(long TimeInMillis) {  
    this.init(TimeInMillis);  
}  
private void init(long TimeInMillis) {  
    this.solar = Calendar.getInstance();  
    this.solar.setTimeInMillis(TimeInMillis);  
    Calendar baseDate = new GregorianCalendar(1900, 0, 31);  
    long offset = (TimeInMillis - baseDate.getTimeInMillis()) / 86400000;  
    // 按農曆年遞減每年的農曆天數,確定農曆年份     
    this.lunarYear = 1900;  
    int daysInLunarYear = Lunar2.getLunarYearDays(this.lunarYear);  
    while (this.lunarYear < 2100 && offset >= daysInLunarYear) {  
        offset -= daysInLunarYear;  
        daysInLunarYear = Lunar2.getLunarYearDays(++this.lunarYear);  
    }  
    // 農曆年數字     

    // 按農曆月遞減每月的農曆天數,確定農曆月份     
    int lunarMonth = 1;  
    // 所在農曆年閏哪個月,若沒有返回0     
    int leapMonth = Lunar2.getLunarLeapMonth(this.lunarYear);  
    // 是否閏年     
    this.isLeapYear = leapMonth > 0;  
    // 閏月是否遞減     
    boolean leapDec = false;  
    boolean isLeap = false;  
    int daysInLunarMonth = 0;  
    while (lunarMonth < 13 && offset > 0) {  
        if (isLeap && leapDec) { // 如果是閏年,並且是閏月     
            // 所在農曆年閏月的天數     
            daysInLunarMonth = Lunar2.getLunarLeapDays(this.lunarYear);  
            leapDec = false;  
        } else {  
            // 所在農曆年指定月的天數     
            daysInLunarMonth = Lunar2.getLunarMonthDays(this.lunarYear, lunarMonth);  
        }  
        if (offset < daysInLunarMonth) {  
            break;  
        }  
        offset -= daysInLunarMonth;  

        if (leapMonth == lunarMonth && isLeap == false) {  
            // 下個月是閏月     
            leapDec = true;  
            isLeap = true;  
        } else {  
            // 月份遞增     
            lunarMonth++;  
        }  
    }  
    this.maxDayInMonth = daysInLunarMonth;  
    // 農曆月數字     
    this.lunarMonth = lunarMonth;  
    // 是否閏月     
    this.isLeap = (lunarMonth == leapMonth && isLeap);  
    // 農曆日數字     
    this.lunarDay = (int) offset + 1;  
    // 取得干支歷     
    this.getCyclicalData();  
} 
/** 
 * 返回農曆年的總天數 
 * 114-162 目的是求農曆的總天數
 * @param lunarYear 指定農曆年份(數字) 
 * @return 該農曆年的總天數(數字) 
 */  
private static int getLunarYearDays(int lunarYear) {  
    // 按小月計算,農曆年最少有12 * 29 = 348天     
    int daysInLunarYear = 348;  
    // 數據表中,每個農曆年用16bit來表示,     
    // 前12bit分別表示12個月份的大小月,最後4bit表示閏月     
    // 每個大月累加一天     
    for (int i = 0x8000; i > 0x8; i >>= 1) {  
        daysInLunarYear += ((Lunar2.lunarInfo[lunarYear - 1900] & i) != 0) ? 1  
                : 0;  
    }  
    // 加上閏月天數     
    daysInLunarYear += Lunar2.getLunarLeapDays(lunarYear);  

    return daysInLunarYear;  
}  
/** 
 * 返回農曆年閏月的天數 
 * 
 * @param lunarYear 指定農曆年份(數字) 
 * @return 該農曆年閏月的天數(數字) 
 */  
private static int getLunarLeapDays(int lunarYear) {  
    // 下一年最後4bit爲1111,返回30(大月)     
    // 下一年最後4bit不爲1111,返回29(小月)     
    // 若該年沒有閏月,返回0     
    return Lunar2.getLunarLeapMonth(lunarYear) > 0 ? ((Lunar2.lunarInfo[lunarYear - 1899] & 0xf) == 0xf ? 30  
            : 29)  
            : 0;  
}  
/** 
 * 返回農曆年閏月月份 
 * 
 * @param lunarYear 指定農曆年份(數字) 
 * @return 該農曆年閏月的月份(數字,沒閏返回0) 
 */  
private static int getLunarLeapMonth(int lunarYear) {  
    // 數據表中,每個農曆年用16bit來表示,     
    // 前12bit分別表示12個月份的大小月,最後4bit表示閏月     
    // 若4bit全爲1或全爲0,表示沒閏, 否則4bit的值爲閏月月份     
    int leapMonth = Lunar2.lunarInfo[lunarYear - 1900] & 0xf;  
    leapMonth = (leapMonth == 0xf ? 0 : leapMonth);  
    return leapMonth;  
}  

/** 
 * 返回農曆年正常月份的總天數 
 * 
 * @param lunarYear 指定農曆年份(數字) 
 * @param lunarMonth 指定農曆月份(數字) 
 * @return 該農曆年閏月的月份(數字,沒閏返回0) 
 */  
private static int getLunarMonthDays(int lunarYear, int lunarMonth) {  
    // 數據表中,每個農曆年用16bit來表示,     
    // 前12bit分別表示12個月份的大小月,最後4bit表示閏月     
    int daysInLunarMonth = ((Lunar2.lunarInfo[lunarYear - 1900] & (0x10000 >> lunarMonth)) != 0) ? 30  
            : 29;  
    return daysInLunarMonth;  
}  
/** 
 * 取干支歷 不是歷年,歷月干支,而是中國的從立春節氣開始的節月,是中國的太陽十二宮,陽曆的。 
 * 
 * @param cncaData 日曆對象(Tcnca) 
 */  
private void getCyclicalData() {  
    this.solarYear = this.solar.get(Calendar.YEAR);  
    this.solarMonth = this.solar.get(Calendar.MONTH);  
    this.solarDay = this.solar.get(Calendar.DAY_OF_MONTH);  
    // 干支歷     
    int cyclicalYear = 0;  
    int cyclicalMonth = 0;  
    int cyclicalDay = 0;  
    int cyclicalHour = 0;
    // 干支年 1900年立春後爲庚子年(60進制36)     
    int term2 = Lunar2.getSolarTermDay(solarYear, 2); // 立春日期     
    // 依節氣調整二月分的年柱, 以立春爲界     
    if (solarMonth < 1 || (solarMonth == 1 && solarDay < term2)) {  
        cyclicalYear = (solarYear - 1900 + 36 - 1) % 60;  
    } else {  
        cyclicalYear = (solarYear - 1900 + 36) % 60;  
    }  

    // 干支月 1900年1月小寒以前爲 丙子月(60進制12)     
    int firstNode = Lunar2.getSolarTermDay(solarYear, solarMonth * 2); // 傳回當月「節」爲幾日開始     
    // 依節氣月柱, 以「節」爲界     
    if (solarDay < firstNode) {  
        cyclicalMonth = ((solarYear - 1900) * 12 + solarMonth + 12) % 60;  
    } else {  
        cyclicalMonth = ((solarYear - 1900) * 12 + solarMonth + 13) % 60;  
    }  

    // 當月一日與 1900/1/1 相差天數     
    // 1900/1/1與 1970/1/1 相差25567日, 1900/1/1 日柱爲甲戌日(60進制10)     
    cyclicalDay = (int) (Lunar2.UTC(solarYear, solarMonth, solarDay, 0, 0, 0) / 86400000 + 25567 + 10) % 60;  
    this.cyclicalYear = cyclicalYear;  
    this.cyclicalMonth = cyclicalMonth;  
    this.cyclicalDay = cyclicalDay;  
}  
/** 
 * 返回公曆年節氣的日期 
 * 
 * @param solarYear 指定公曆年份(數字) 
 * @param index 指定節氣序號(數字,0從小寒算起) 
 * @return 日期(數字,所在月份的第幾天) 
 */  
private static int getSolarTermDay(int solarYear, int index) {  

    return Lunar.getUTCDay(getSolarTermCalendar(solarYear, index));  
}  
/** 
 * 返回公曆年節氣的日期 
 * 
 * @param solarYear 指定公曆年份(數字) 
 * @param index 指定節氣序號(數字,0從小寒算起) 
 * @return 日期(數字,所在月份的第幾天) 
 */  
public static Date getSolarTermCalendar(int solarYear, int index) {  
    long l = (long) 31556925974.7 * (solarYear - 1900)  
            + solarTermInfo[index] * 60000L;  
    l = l + Lunar.UTC(1900, 0, 6, 2, 5, 0);  
    return new Date(l);  
}
/** 
 * 返回全球標準時間 (UTC) (或 GMT) 的 1970 年 1 月 1 日到所指定日期之間所間隔的毫秒數。 
 * 
 * @param y 指定年份 
 * @param m 指定月份 
 * @param d 指定日期 
 * @param h 指定小時 
 * @param min 指定分鐘 
 * @param sec 指定秒數 
 * @return 全球標準時間 (UTC) (或 GMT) 的 1970 年 1 月 1 日到所指定日期之間所間隔的毫秒數 
 */  
public static synchronized long UTC(int y, int m, int d, int h, int min, int sec) {  
    Lunar2.makeUTCCalendar();  
    synchronized (utcCal) {  
        utcCal.clear();  
        utcCal.set(y, m, d, h, min, sec);  
        return utcCal.getTimeInMillis();  
    }  
}  
private static synchronized void makeUTCCalendar() {  
    if (Lunar2.utcCal == null) {  
        Lunar2.utcCal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));  
    }  
}  
//----------------------------------------------------干支歷
/** 
 * 取得干支歷字符串 
 * 
 * @return 干支歷字符串(例:甲子年甲子月甲子日) 
 */  
public String getCyclicalDateString() {  
    this.getCyclicaMonth();
    String s = "巳";
    String hours = null;
    //判斷時辰
    String hour = getCyclicaDay().substring(0,1);
    if (hour.equals("甲")||hour.equals("己")) {
        String[] hor = {"甲子","乙丑","丙寅","丁卯","戊辰","己巳","庚午","辛未","壬申","癸酉","甲戌","乙亥"};
        for(String a : hor) {
            if(a.substring(1, 2).equals(s)) {
                hours = a;
            }
        }       
    }else if (hour.equals("乙")||hour.equals("庚")) {
        String[] hor = {"丙子","丁丑","戊寅","己卯","庚辰","辛巳","壬午","癸未","甲申","乙酉","丙戌","丁亥"};
        for(String a : hor) {
            if(a.substring(1, 2).equals(s)) {
                hours = a;
            }
        }       
    }else if (hour.equals("丙")||hour.equals("辛")) {
        String[] hor = {"戊子","己丑","庚寅","辛卯","壬辰","癸巳","甲午","乙未","丙申","丁酉","戊戌","己亥"};
        for(String a : hor) {
            if(a.substring(1, 2).equals(s)) {
                hours = a;
            }
        }       
    }else if (hour.equals("丁")||hour.equals("壬")) {
        String[] hor = {"庚子","辛丑","壬寅","癸卯","甲辰","乙巳","丙午","丁未","戊申","己酉","庚戌","辛亥"};
        for(String a : hor) {
            if(a.substring(1, 2).equals(s)) {
                hours = a;
            }
        }       
    }else {
        String[] hor = {"壬子","癸丑","甲寅","乙卯","丙辰","丁巳","戊午","己未","庚申","辛酉","壬戌","癸亥"};
        for(String a : hor) {
            if(a.substring(1, 2).equals(s)) {
                hours = a;
            }
        }   
    }
    return this.getCyclicaYear() + "年" + this.getCyclicaMonth() + "月"  
            + this.getCyclicaDay() + "日"+hours+"時";  
} 
/** 
 * 取得干支月字符串 
 * 
 * @return 干支月字符串 
 */  
public String getCyclicaMonth() {  
    return Lunar2.getCyclicalString(this.cyclicalMonth);  
}  
/** 
 * 干支字符串 
 * 
 * @param cyclicalNumber 指定干支位置(數字,0爲甲子) 
 * @return 干支字符串 
 */  
private static String getCyclicalString(int cyclicalNumber) {  
    return Lunar2.Tianan[Lunar2.getTianan(cyclicalNumber)] + Lunar2.Deqi[Lunar2.getDeqi(cyclicalNumber)];  
}  
/** 
 * 獲得天干 
 * 
 * @param cyclicalNumber 
 * @return 天干 (數字) 
 */  
private static int getTianan(int cyclicalNumber) {  
    return cyclicalNumber % 10;  
} 
/** 
 * 獲得地支 
 * 
 * @param cyclicalNumber 
 * @return 地支 (數字) 
 */  
private static int getDeqi(int cyclicalNumber) {  
    return cyclicalNumber % 12;  
}  
/** 
 * 取得干支年字符串 
 * 
 * @return 干支年字符串 
 */  
public String getCyclicaYear() {  
    return Lunar2.getCyclicalString(this.cyclicalYear);  
}  
/** 
 * 取得干支日字符串 
 * 
 * @return 干支日字符串 
 */  
public String getCyclicaDay() {  
    return Lunar2.getCyclicalString(this.cyclicalDay);  
} 

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章