티스토리 뷰
하고 있던 작업이 슬슬 지겨워질 무렵... 문득, 음력변환에 관한 궁금증이 생기더라. 여태 프로그래밍할 때, 음력을 쓸 일은 없었지만.. 언젠가는 쓰지 않을까하는 막연한 추측에 사로잡혀 관련 자료를 찾기 시작했다. 대충 2가지 소스로 압축. 하나는 델파이로 프로그래밍된 "진짜 만세력" 이라는 프로그램과 하나는 꽤 오래된 듯한 C 소스였다. 일단 "진짜 만세력"이라는 프로그램의 소스코드를 개발자가 공개해놓아서 이걸 먼저 열어봤다. 이런 상황으로 인해 델파이 소스는 포기하고 C 언어 소스를 가져다가 C# (.NET Framework 2.0)으로 포팅하기 시작했다. 일단 양력을 음력으로 바꾸는 부분만 포팅해서 확인해 보니.. 잘 돌아가는 듯이 보인다. 그런데, 시간을 가지고 천천히 확인해 보니... 날짜 계산이 잘못되는 부분이 상당히 많다. 하루씩 뒤로 밀리는 달이 있기도 하고, 아무래도 소스에 기록된 기초데이터(음양력변환표)가 잘못되어 있다는 생각에 비슷한 부류의 다른 소스를 찾아보니 이 소스들도 똑 같은 결과를 보인다. 본인 추측으론 최초에 공개된 소스의 기초데이터에 오류가 있고, 이걸 수정해서 만든 거의 모든 소스에 같은 오류가 있는 것 같다. 가장 현명한 방법은 계산에서 사용하는 150~200년치 음양력변환표를 찾아서 데이터를 수정하는 것이지 않을까? 나는 음력계산이 양력(그레고리오력)처럼 간단한 공식으로 해결될 줄 알았다. 그런데, 관련 자료를 읽다보니 우리가 사용하는 음력(태음태양력) 자체가 계산오차가 상당하고 태양과 달의 주기를 관측해서 계산하는 역법이라는 사실을 알았다. 한마디로 천체 데이터가 없으면 계산 자체가 안되는.. 무지랭이 입장에선 심각히 복잡해 보이는 역법이다. [참고]
난감한 상황에서 이리저리 잔머리를 굴리다가 혹시나 하고 MSDN 라이브러리를 뒤져보니. EastAsianLunisolarCalendar 클래스는 abstract 클래스로 선언되어 있어서 바로 사용할 수 없고, 이 클래스에서 파생된 것 중에 하나를 써야 한다. 총 4개의 파생 클래스가 존재하는데 순서대로 적으면 아래와 같다.
같은 태음태양력이라 할지라도 어느 기준시에 따라 계산하느냐에 따라 날짜가 달라진다. 예를 들어, 우리나라는 어느 해 1월이 29일까지만 있는 작은 달인데, 우리와 인접한 중국은 30일까지 있는 큰 달일 수 있다. 이는 우리나라에서 사용하는 기준시(KST, GMT+9)가 중국과 다른 까닭이다. 그러므로 반드시 우리나라에서 사용하는 음력을 계산할 때 KoreanLunisolarCalandar 클래스를 사용해야 한다. [참고]
음력은 날짜수가 작은 달은 29일, 큰 달은 30일이다. 양력처럼 31일이 없기 때문에 1년의 전체 날짜수는 354일 혹은 355일이 된다. 태양력에서 사용하는 356일과 11일 정도의 오차가 발생하기 때문에 이대로 사용하면 계절과 달(月)이 서로 불일치하는 현상을 보인다. 그래서 19년에 7번 윤달을 삽입하는데, 윤달이 들어 있는 윤년의 경우 총 13개월이 되고 전체 날짜수는 383일 혹은 384일이 된다. MSDN 라이브러리에 나와있는 KoreanLunisolarCalendar 클래스에 대한 설명이나 예제가 매우 빈약한 관계로 이 클래스를 사용해서 날짜 변환에 대한 개념을 잡기조차도 힘들더라. 하여간 이런저런 삽질 끝에 코딩한 양력 -> 음력 변환 코드는 아래와 같다. public static LunisolarDate ConvertFromSolarDate(DateTime solarDate) date._solarDate = solarDate; // 양력 년월일 // 윤달이 끼어 있으면.. 너무 너무 간단하지 않은가? 양력날짜인 DateTime solarDate 파라미터를 전달받아서 LunisolarDate라고 이름지은 음력계산 클래스의 새 인스턴스를 생성시키는 static 메서드다. 전체 코드는 프로젝트 파일(Vistual Studio 2005)과 함께 압축하여 첨부했으니 참고하시길. 이제 음력에서 양력을 계산하는 코드를 보자. public LunisolarDate(int year, int month, int day, bool isLeapMonth) // 간지 및 띠 계산은 양력날짜를 기준으므로 하므로 음력을 전달받는 클래스 생성자인데, 이 역시 비교적 간단한 편이다. 태음태양력에선 윤달이 끼어 있는 해(年)는 총 13개월이다. 예를 들면, 1월, 2월, 3월, 윤3월, 4월 이런식으로. 그렇다고 사용자에게 2008년 13월 20일이라고 알려줄 순 없지않은가? 하여튼 이렇게 대충 만든 클래스를 시연해볼 필요가 있어 아래 화면의 데모용 폼을 만들었다.
설명
[주의]
| |