728x90

[ 태음력의 조정 ]
    235회합월은 일수로는 6940일(days)이다(235 x 29.530588일 = 6939.68818일).
    6940일의 1/19은 6940일 / 19 = 365.263157894737일(365 + 1/4 + 1/76일)이다.
    365.263157894737일은 12회합월(synodic months)인
    12 x 29.530588일 = 354.367056일보다 10.896101894737일(365.263157894737 - 354.367056) 더 크다.
    이것이 뜻하는 바는 음력으로 1년이 지나면 태양력과는 약 11일의 차이가 난다는 것을 의미한다.
    따라서 음력으로 3년이 지나면 태양력과는 약 33일의 차이가 나게 된다.
    따라서 3년마다 음력에 1달을 추가하며 13개의 음력 달들이 있게 하면,
    태음력은 어느 정도 근사하게 태양력과 일치하게 된다.
    태양력 19년 동안에 이런 작업을 총 7번(19년/3년 = 6.33) 행하면 된다.
    이런 이유로, 메톤 주기를 19년 7윤법이라고도 하였다.
 
메톤은 19태양년을 6,940일로 보고,
이것을 큰달(30일) 125개월과 작은달(29일) 110개월의 총 235개월 6,940일로 배분하였다.
이 방법은 평년(12개월) 12년과 윤년(13개월) 7년의 총 235개월로
태음력 달력을 구성하는 것과 동일하므로 19년 7윤법이라고도 하였다.

메톤주기의 존재를 알 수 있는 예로,
특정한 양력 날짜와 그에 대응하는 음력 날짜는 19년이 지나면 다시 일치한다는 사실을 찾을 수 있다.

하지만 정확히 맞물리는 건 아니라서 하루 정도 어긋나기도 한다. 


음력 날짜는 어느 경도를 기준으로 했느냐에 따라 하루 정도 차이가 있어서 때려 맞춰야 한다는 얘기가 있다.

한국천문연구원에서 계산한 2050년까지 음양력 자료들이 수록된 만세력을 기준으로 음력 날짜를 맞추면 될 거 같다.

음력을 알아내는 일정한 규칙은 없다고 한다.

아래 변환 코드로 내 생년월일, 딸래미 생년월일을 양력 → 음력 변환을 했을 때는 정확하게 결과가 도출되었다.


검색한 걸 참고하면 도움될 거 같아서 링크를 걸어둔다.

http://lifesci.net/pod/bbs/board.php?bo_table=B01&wr_id=1917



PHP 달력 만들기 https://link2me.tistory.com/1545 코드에 있는 함수를 자바 코드로 변환을 했다.

자동 변환이 아니라 코드에 맞게 함수를 찾아서 수정했다.

음력이 지원되는 Custom 달력을 만들어 볼 목적으로 코드를 변환하여 테스트 해보는 중이다.

PHP 원본 코드와 Java 로 변환한 코드를 같이 첨부했다.

Java 변환 코드는 Android 에서 활용하기 위한 목적이라 Android Studio 에서 작성했다.


PHP 코드

lun2sol.php



Lunar2Solar.java

Lunar2Solar.java

Lunar2Solar.java


자바 음력/양력 변환 코드

public class Lunar2Solar {
    // 음력 데이터 (평달 - 작은달 :1,  큰달:2 )
    // (윤달이 있는 달 - 평달이 작고 윤달도 작으면 :3 , 평달이 작고 윤달이 크면 : 4)
    // (윤달이 있는 달 - 평달이 크고 윤달이 작으면 :5,  평달과 윤달이 모두 크면 : 6)
    final static String[] LunarInfo = new String[]
            {"1212122322121","1212121221220","1121121222120","2112132122122","2112112121220",
                "2121211212120","2212321121212","2122121121210","2122121212120","1232122121212",
                "1212121221220","1121123221222","1121121212220","1212112121220","2121231212121",
                "2221211212120","1221212121210","2123221212121","2121212212120","1211212232212",
                "1211212122210","2121121212220","1212132112212","2212112112210","2212211212120",
                "1221412121212","1212122121210","2112212122120","1231212122212","1211212122210",
                "2121123122122","2121121122120","2212112112120","2212231212112","2122121212120",
                "1212122121210","2132122122121","2112121222120","1211212322122","1211211221220",
                "2121121121220","2122132112122","1221212121120","2121221212110","2122321221212",
                "1121212212210","2112121221220","1231211221222","1211211212220","1221123121221",
                "2221121121210","2221212112120","1221241212112","1212212212120","1121212212210",
                "2114121212221","2112112122210","2211211412212","2211211212120","2212121121210",
                "2212214112121","2122122121120","1212122122120","1121412122122","1121121222120",
                "2112112122120","2231211212122","2121211212120","2212121321212","2122121121210",
                "2122121212120","1212142121212","1211221221220","1121121221220","2114112121222",
                "1212112121220","2121211232122","1221211212120","1221212121210","2121223212121",
                "2121212212120","1211212212210","2121321212221","2121121212220","1212112112210",
                "2223211211221","2212211212120","1221212321212","1212122121210","2112212122120",
                "1211232122212","1211212122210","2121121122210","2212312112212","2212112112120",
                "2212121232112","2122121212110","2212122121210","2112124122121","2112121221220",
                "1211211221220","2121321122122","2121121121220","2122112112322","1221212112120",
                "1221221212110","2122123221212","1121212212210","2112121221220","1211231212222",
                "1211211212220","1221121121220","1223212112121","2221212112120","1221221232112",
                "1212212122120","1121212212210","2112132212221","2112112122210","2211211212210",
                "2221321121212","2212121121210","2212212112120","1232212122112","1212122122110",
                "2121212322122","1121121222120","2112112122120","2211231212122","2121211212120",
                "2122121121210","2124212112121","2122121212120","1212121223212","1211212221220",
                "1121121221220","2112132121222","1212112121220","2121211212120","2122321121212",
                "1221212121210","2121221212120","1232121221212","1211212212210","2121123212221",
                "2121121212220","1212112112220","1221231211221","2212211211220","1212212121210",
                "2123212212121","2112122122120","1211212322212","1211212122210","2121121122120",
                "2212114112122","2212112112120","2212121211210","2212232121211","2122122121210",
                "2112122122120","1231212122212","1211211221220","2121121321222","2121121121220",
                "2122112112120","2122141211212","1221221212110","2121221221210","2114121221221"};

    final static int[] arrayLDAY = new int[]{31,0,31,30,31,30,31,31,30,31,30,31};

    public static String lun2sol(String yyyymmdd) {
        int YunMonthFlag = 0;
        int gf_lun2sol = 0;
        int gf_yun = 0;
        int leap = 0;
        int syear = 0;
        int smonth = 0;
        int sday = 0;

        int getYEAR = Integer.parseInt(yyyymmdd.substring(0,4));
        int getMONTH = Integer.parseInt(yyyymmdd.substring(4,6));
        int getDAY = Integer.parseInt(yyyymmdd.substring(6,8));

        String arrayYUKSTR="甲-乙-丙-丁-戊-己-庚-辛-壬-癸";
        String[] arrayYUK = arrayYUKSTR.split("-");

        String arrayGAPSTR="子-丑-寅-卯-辰-巳-午-未-申-酉-戌-亥";
        String[] arrayGAP = arrayGAPSTR.split("-");

        String arrayDDISTR="쥐-소-범-토끼-용-뱀-말-양-원숭이-닭-개-돼지";
        String[] arrayDDI = arrayDDISTR.split("-");

        String arrayWEEKSTR="일-월-화-수-목-금-토";
        String[] arrayWEEK = arrayWEEKSTR.split("-");

        if (getYEAR <= 1881 || getYEAR >= 2050) { //년수가 해당일자를 넘는 경우
            YunMonthFlag = 0;
        }

        if (getMONTH > 12) { // 달수가 13이 넘는 경우
            YunMonthFlag = 0;
        }

        int m1 = getYEAR - 1881;
        if (Integer.parseInt(LunarInfo[m1].substring(12,13)) == 0) { // 윤달이 없는 해임
            YunMonthFlag = 0;
        } else {
            if (Integer.parseInt(LunarInfo[m1].substring(getMONTH,getMONTH+1)) > 2) {
                YunMonthFlag = 1;
            } else {
                YunMonthFlag = 0;
            }
        }

        m1 = -1;
        int td = 0;

        if (getYEAR > 1881 && getYEAR < 2050) {
            m1 = getYEAR - 1882;
            for (int i=0; i <= m1; i++) {
                for (int j=0; j <= 12; j++) {
                    td = td + Integer.parseInt(LunarInfo[i].substring(j,j+1));
                }
                if (Integer.parseInt(LunarInfo[i].substring(12,13)) == 0) {
                    td = td + 336;
                } else {
                    td = td + 362;
                }
            }
        } else {
            gf_lun2sol = 0;
        }

        m1++;
        int n2 = getMONTH - 1;
        int m2 = -1;

        while(true) {
            m2++;
            if (Integer.parseInt(LunarInfo[m1].substring(m2,m2+1)) > 2) {
                td = td + 26 + Integer.parseInt(LunarInfo[m1].substring(m2,m2+1));
                n2++;
            } else {
                if (m2 == n2) {
                    if (gf_yun == 1) {
                        td = td + 28 + Integer.parseInt(LunarInfo[m1].substring(m2,m2+1));
                    }
                    break;
                } else {
                    td = td + 28 + Integer.parseInt(LunarInfo[m1].substring(m2,m2+1));
                }
            }
        }

        td = td + getDAY + 29;
        m1 = 1880;
        while(true) {
            m1++;
            if (m1 % 400 == 0 || m1 % 100 != 0 && m1 % 4 == 0) {
                leap = 1;
            } else {
                leap = 0;
            }

            if (leap == 1) {
                m2 = 366;
            } else {
                m2 = 365;
            }

            if (td < m2) break;
            td = td - m2;
        }
        syear = m1;
        arrayLDAY[1] = m2 - 337;

        m1 = 0;

        while(true) {
            m1++;
            if (td <= arrayLDAY[m1-1]) {
                break;
            }
            td = td - arrayLDAY[m1-1];
        }
        smonth = m1;
        sday = td;
        int y = syear - 1;
        td = (int)(y*365) + (int)(y/4) - (int)(y/100) + (int)(y/400);

        if (syear % 400 == 0 || syear % 100 != 0 && syear % 4 == 0) {
            leap = 1;
        } else {
            leap = 0;
        }

        if (leap == 1) {
            arrayLDAY[1] = 29;
        } else {
            arrayLDAY[1] = 28;
        }
        for (int i=0; i <= smonth-2; i++) {
            td = td + arrayLDAY[i];
        }
        td = td + sday;
        int w = td % 7;

        String sweek = arrayWEEK[w];
        gf_lun2sol = 1;

        return String.valueOf(syear+String.format("%02d", smonth)+String.format("%02d", sday));
    }

    public static String sol2lun(String yyyymmdd) {
        int gf_sol2lun = 0;
        int gf_yun = 0;

        int getYEAR = Integer.parseInt(yyyymmdd.substring(0,4));
        int getMONTH = Integer.parseInt(yyyymmdd.substring(4,6));
        int getDAY = Integer.parseInt(yyyymmdd.substring(6,8));

        String arrayYUKSTR="甲-乙-丙-丁-戊-己-庚-辛-壬-癸";
        String[] arrayYUK = arrayYUKSTR.split("-");

        String arrayGAPSTR="子-丑-寅-卯-辰-巳-午-未-申-酉-戌-亥";
        String[] arrayGAP = arrayGAPSTR.split("-");

        String arrayDDISTR="쥐-소-범-토끼-용-뱀-말-양-원숭이-닭-개-돼지";
        String[] arrayDDI = arrayDDISTR.split("-");

        String arrayWEEKSTR="일-월-화-수-목-금-토";
        String[] arrayWEEK = arrayWEEKSTR.split("-");


        Long[] dt = new Long[LunarInfo.length];
        for (int i = 0; i < LunarInfo.length; i++) {
            dt[i] = Long.parseLong(LunarInfo[i]);
        }
        for (int i=0; i <= 168; i++) {
            dt[i] = Long.valueOf(0);
            for (int j=0;j < 12;j++) {
                switch (Integer.parseInt(LunarInfo[i].substring(j,j+1))) {
                    case 1:
                        dt[i] += 29;
                        break;
                    case 3:
                        dt[i] += 29;
                        break;
                    case 2:
                        dt[i] += 30;
                        break;
                    case 4:
                        dt[i] += 30;
                        break;
                }
            }

            switch (Integer.parseInt(LunarInfo[i].substring(12,13))) {
                case 0:
                    break;
                case 1:
                    dt[i] += 29;
                    break;
                case 3:
                    dt[i] += 29;
                    break;
                case 2:
                    dt[i] += 30;
                    break;
                case 4:
                    dt[i] += 30;
                    break;
            }
        }

        int td1 = 1880 * 365 + (int)(1880/4) - (int)(1880/100) + (int)(1880/400) + 30;
        int k11 = getYEAR - 1;

        int td2 = k11 * 365 + (int)(k11/4) - (int)(k11/100) + (int)(k11/400);

        if (getYEAR % 400 == 0 || getYEAR % 100 != 0 && getYEAR % 4 == 0) {
            arrayLDAY[1] = 29;
        } else {
            arrayLDAY[1] = 28;
        }

        if (getMONTH > 13) {
            gf_sol2lun = 0;
        }

        if (getDAY > arrayLDAY[getMONTH-1]) {
            gf_sol2lun = 0;
        }

        for (int i=0;i <= getMONTH-2;i++) {
            td2 += arrayLDAY[i];
        }

        td2 += getDAY;
        int td = td2 - td1 + 1;
        Long td0 = dt[0];

        int jcount = 0;
        int ryear = 0;
        int m1 = 0;
        int m2 = 0;
        int i = 0;
        for (i=0; i <= 168; i++) {
            if (td <= td0) {
                break;
            }
            td0 += dt[i + 1];
        }
        ryear = i + 1881;
        td0 -= dt[i];
        td -= td0;

        if (Integer.parseInt(LunarInfo[i].substring(12,13)) == 0) {
            jcount = 11;
        } else {
            jcount = 12;
        }

        for (int j=0;j <= jcount;j++) { // 달수 check, 윤달 > 2 (by harcoon)
            if (Integer.parseInt(LunarInfo[i].substring(j,j+1)) <= 2) {
                m2++;
                m1 = Integer.parseInt(LunarInfo[i].substring(j,j+1)) + 28;
                gf_yun = 0;
            } else {
                m1 = Integer.parseInt(LunarInfo[i].substring(j,j+1)) + 26;
                gf_yun = 1;
            }
            if (td <= m1) {
                break;
            }
            td = td - m1;
        }

        int k1=(ryear+6) % 10;
        String syuk = arrayYUK[k1];
        int k2=(ryear+8) % 12;
        String sgap = arrayGAP[k2];
        String sddi = arrayDDI[k2];

        gf_sol2lun = 1;

        return String.valueOf(ryear+String.format("%02d", m2)+String.format("%02d", td)+"|"+syuk+sgap+"년|"+sddi+"띠");
    }

}


샘플 코드

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.tistory.link2me.util.LunarCalendar;
import java.util.Calendar;

public class CalendarActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calendar);

        System.out.println("이순신 음력 => 양력 : "+ Lunar2Solar.lun2sol("19961112"));
        System.out.println("홍길동 양력 => 음력 : "+ Lunar2Solar.sol2lun("20010125"));
    }

}
 


Logcat

I/System.out: 이순신 음력 => 양력 : 19961222
I/System.out: 홍길동 양력 => 음력 : 2001|01|02|신사년|뱀띠

이 음력/양력 변환 코드가 자바 버전으로 돌아다니는 것은 없는거 같다.

PHP 코드를 자바로 변환한 것이지만 나름 유용하게 사용할 수 있을 것으로 본다.


이 글이 도움 되었다면 XX 클릭 해주세요. 좋은 자료 올리는데 큰 힘이 됩니다.

블로그 이미지

Link2Me

,
728x90
MySQL 로 된 데이터를 SQLite 로 변환하기 위해서 assets 를 이용할 까 해봤는데, 데이터 크기가 5MB가 넘어서 어플의 용량이 커지는 문제가 발생하고 변환하는데 시간도 걸리고 해서 포기했다.

결국에는 양력/음력 변환을 제대로 해주는 메소드를 잘 만들거나, 기존에 만들어진 다른 코드를 변환해서 이용하는 방법이 최선인 거 같다.
제대로 된 Java 라이브러리가 어디에 있는데 못찾는 것인지, 공개를 안해서 못 구하는 것인지는 모르겠다.


자바에서 제공하는 라이브러리를 이용하여 변환하는 방법을 시도했다.
인터넷 검색하면 가장 많이 나오는 방법이다.


1. https://github.com/unicode-org/icu/releases/tag/release-4-8-2 에서 jar 파일을 다운로드 한다.

http://site.icu-project.org/download/48#ICU4J-Download 페이지의 중간 정도에 Version: 4.8.2
Release Date: 2019-04-11 라고 나온다.


2. 다운로드 받은 파일 icu4j-4_8_2.jar 를 libs 폴더로 복사하거나 옮긴다.


3. dependencies 에 추가한다.

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'gun0912.ted:tedpermission:2.0.0'
    implementation 'com.github.bumptech.glide:glide:3.8.0' // 이미지 라이브러리
    implementation files('libs/icu4j-4_8_2.jar')
}

* 자동 추가 방법은 Android Studio 왼쪽 메뉴에서 Project 로 선택하고 해당 파일에서 마우스 우클릭을 하면 Add As Library... 를 선택하여 추가하면 된다. 직접 dependencies 에 적어주고 Sync Now를 해도 된다.


4. 음력/양력 변환 코드

import com.ibm.icu.util.ChineseCalendar;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;

public class LunarCalendar {
    /**
     * 음력날짜를 양력날짜로 변환
     * @param 음력날짜 (yyyyMMdd)
     * @return 양력날짜 (yyyyMMdd)
     */
    public static String Lunar2Solar(String yyyymmdd) {
        ChineseCalendar cc = new ChineseCalendar();
        Calendar cal = Calendar.getInstance();

        if (yyyymmdd == null)
            return "";

        String date = yyyymmdd.trim();
        if (date.length() != 8) {
            if (date.length() == 4)
                date = date + "0101";
            else if (date.length() == 6)
                date = date + "01";
            else if (date.length() > 8)
                date = date.substring(0, 8);
            else
                return "";
        }

        cc.set(ChineseCalendar.EXTENDED_YEAR, Integer.parseInt(date.substring(0, 4)) + 2637);
        cc.set(ChineseCalendar.MONTH, Integer.parseInt(date.substring(4, 6)) - 1);
        cc.set(ChineseCalendar.DAY_OF_MONTH, Integer.parseInt(date.substring(6)));

        cal.setTimeInMillis(cc.getTimeInMillis());

        int y = cal.get(Calendar.YEAR);
        int m = cal.get(Calendar.MONTH) + 1;
        int d = cal.get(Calendar.DAY_OF_MONTH);

        StringBuffer ret = new StringBuffer();
        ret.append(String.format("%04d", y));
        ret.append(String.format("%02d", m));
        ret.append(String.format("%02d", d));

        return ret.toString();
    }

    /**
     * 양력날짜를 음력날짜로 변환
     * @param 양력날짜 (yyyyMMdd)
     * @return 음력날짜 (yyyyMMdd)
     */
    public static String Solar2Lunar(String yyyymmdd) {
        ChineseCalendar cc = new ChineseCalendar();
        Calendar cal = Calendar.getInstance();

        if (yyyymmdd == null)
            return "";

        String date = yyyymmdd.trim() ;
        if( date.length() != 8 ) {
            if( date.length() == 4 )
                date = date + "0101" ;
            else if( date.length() == 6 )
                date = date + "01" ;
            else if( date.length() > 8 )
                date = date.substring(0,8) ;
            else
                return "" ;
        }

        cal.set( Calendar.YEAR, Integer.parseInt(date.substring(0,4)) ) ;
        cal.set( Calendar.MONTH, Integer.parseInt(date.substring(4,6))-1 ) ;
        cal.set( Calendar.DAY_OF_MONTH, Integer.parseInt(date.substring(6)) ) ;

        cc.setTimeInMillis( cal.getTimeInMillis() ) ;

        // ChinessCalendar.YEAR 는 1~60 까지의 값만 가지고 ,
        // ChinessCalendar.EXTENDED_YEAR 는 Calendar.YEAR 값과 2637 만큼의 차이를 가진다.
        int y = cc.get(ChineseCalendar.EXTENDED_YEAR)-2637 ;
        int m = cc.get(ChineseCalendar.MONTH)+1 ;
        int d = cc.get(ChineseCalendar.DAY_OF_MONTH) ;

        StringBuffer ret = new StringBuffer() ;
        if( y < 1000 )          ret.append( "0" ) ;
        else if( y < 100 )      ret.append( "00" ) ;
        else if( y < 10 )       ret.append( "000" ) ;
        ret.append( y ) ;

        if( m < 10 ) ret.append( "0" ) ;
        ret.append( m ) ;

        if( d < 10 ) ret.append( "0" ) ;
        ret.append( d ) ;

        return ret.toString() ;
    }
}


5. 샘플 코드

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.tistory.link2me.util.LunarCalendar;
import java.util.Calendar;

public class CalendarActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calendar);

        System.out.println( LunarCalendar.Solar2Lunar("20010715") ) ; // 양력을 음력으로 바꾸기
        System.out.println( LunarCalendar.Lunar2Solar("20010527") ) ; // 음력을 양력으로 바꾸기
    }


이 라이브러리를 이용하는 방법은 간단하기는 한데 정교한 맛이 없는 거 같다.

윤달인지 여부, 간지 등을 표현할 수가 없는 점이 좀 아쉽다.


그래서 구글 검색을 하여 Java Lunar Calendar (Lunar Calendar) Tools 를 찾아봤더니

https://www.cnblogs.com/harry335/p/4861598.html 가 검색된다.

이걸 테스트해봤더니 음력일자 결과가 제대로 반환되지 않고 하루가 틀리게 나온다.

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

public class Ca03 {
    private int year;
    private int month;
    private int day;
    private boolean leap;
    final static String chineseNumber[] = { "1", "2", "3", "4", "5", "6", "7","8", "9", "10", "11", "12" };
    static SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
    final static long[] lunarInfo = new long[] { 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, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950,
            0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,
            0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0,
            0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 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 };

    // ====== 传回农历 y年的总天数
    final private static 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年闰月的天数
    final private static int leapDays(int y) {
        if (leapMonth(y) != 0) {
            if ((lunarInfo[y - 1900] & 0x10000) != 0)
                return 30;
            else
                return 29;
        } else
            return 0;
    }

    // ====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
    final private static int leapMonth(int y) {
        return (int) (lunarInfo[y - 1900] & 0xf);
    }

    // ====== 传回农历 y年m月的总天数
    final private static int monthDays(int y, int m) {
        if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)
            return 29;
        else
            return 30;
    }

    // ====== 传回农历 y年的生肖
    final public String animalsYear() {
        final String[] Animals = new String[] { "쥐", "소", "호랑이", "토끼", "용", "뱀", "말", "양", "원숭이", "닭", "개", "돼지"};
        return Animals[(year - 4) % 12];
    }

    // ====== 传入 月日的offset 传回干支, 0=甲子
    final private static String cyclicalm(int num) {
        final String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };
        final String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };
        return (Gan[num % 10] + Zhi[num % 12]);
    }

    // ====== 传入 offset 传回干支, 0=甲子
    final public String cyclical() {
        int num = year - 1900 + 36;
        return (cyclicalm(num));
    }

    public Ca03(Calendar cal) {
        int yearCyl, monCyl, dayCyl;
        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);
        dayCyl = offset + 40;
        monCyl = 14;

        // 用offset减去每农历年的天数
        // 计算当天是农历第几天
        // i最终结果是农历的年份
        // offset是当年的第几天
        int iYear, daysOfYear = 0;
        for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) {
            daysOfYear = yearDays(iYear);
            offset -= daysOfYear;
            monCyl += 12;
        }
        if (offset < 0) {
            offset += daysOfYear;
            iYear--;
            monCyl -= 12;
        }
        // 农历年份
        year = iYear;

        yearCyl = iYear - 1864;
        leapMonth = leapMonth(iYear); // 闰哪个月,1-12
        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;
            if (!leap)
                monCyl++;
        }
        // offset为0时,并且刚才计算的月份是闰月,要校正
        if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
            if (leap) {
                leap = false;
            } else {
                leap = true;
                --iMonth;
                --monCyl;
            }
        }
        // offset小于0时,也要校正
        if (offset < 0) {
            offset += daysOfMonth;
            --iMonth;
            --monCyl;
        }
        month = iMonth;
        day = offset + 1;
    }

    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 "初十";
        else
            return chineseTen[day / 10] + chineseNumber[n];
    }

    public String toString() {
        return year + "年 " + (leap ? "闰" : "") + chineseNumber[month - 1] + "月 " + day +"日";
    }
   
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        cal.setTimeZone(TimeZone.getDefault());
        System.out.println("양력(오늘):" + sdf.format(cal.getTime()));
       
        int year = 2001;
        int month = 1;
        int date = 25;
        cal.set(year, month-1, date);

        Ca03 lunar = new Ca03(cal);
        System.out.print("음력(오늘):");
        System.out.print(lunar.year + "年 ");
        System.out.print(lunar.month + "月 ");
        System.out.print(lunar.day+"日");

        System.out.println("\n*************\n" + lunar.animalsYear());
        System.out.println(lunar.cyclical());
        System.out.println(lunar);
    }

}



PHP 로 된 만세력 변환 코드가 올려져 있는 거 같다.

https://github.com/OOPS-ORG-PHP/Lunar/releases

이 코드를 변환해 보지는 않았다.


다음에는 PHP 에서 음력/양력 변환하는 코드를 자바로 변환해본 것을 올릴 것이다.

블로그 이미지

Link2Me

,