LuniSolarCal: 율리우스 적일을 음력으로 바꾸는 함수
Type LunarDayStartDay As Double '삭망월의 시작일(=정삭일)MonLength As Integer '달의 길이(큰 달=30일, 작은 달=29일)Junggi As Boolean '무중월, 유중월 여부(무중월이면 거짓)MonName As Byte '월 이름(월 번호)LYear As Integer '삭망월이 포함된 연도End Type
Private Sub LuniSolarCal(ByVal jd As Double, LunarYear As Integer, LunarMon As Byte, LunarDay As Byte, IsLeap As Boolean)
Dim jd0 As Double, dYear As Double, yJD0 As Double, bf As Double, B As Integer, M As Integer
Dim i As Integer, j As Integer, k As Integer, LD(25) As LunarDay, SD(25) As Double
Dim PreWinter As Double, ThisWinter As Double, Count1 As Integer, idx1 As Integer, idx2 As Integer
Dim LeapType As Byte, Leap13 As Boolean, fMON As Integer, A As Integer, LCount As Integer
jd0 = GetJD0(jd) + 0.5 '입력일을 정오로 설정
dYear = InvJDYear(jd0) '입력일의 연도 계산
'입력일이 천정동지일 이전이면 계산 주기를 1년 앞으로, 입력일 연도이 동지 이후이면 1년 뒤로 바꿈.
If jd0 < cJunggi(dYear, 270, -13) Then dYear = dYear - 1
If jd0 > cJunggi(dYear, 270, 355) Then dYear = dYear + 1
'입력일 연도의 1일의 율리우스 적일 계산
yJD0 = JULIANDAY(dYear, 1, 1)
Call Set24Julgi: CalcJulGi yJD0 '24절기 입기시각 계산
'정삭시각을 계산하여 배열에 저장(해당연도 1월 1일을 기준으로 96일 이전부터 이후 427일 사이의 기간)
j = 0: SD(0) = 0: k = 0
Do
bf = GetJD0(NewMoon(yJD0 - 96 + j * 28)) + 0.5
If bf >= Junggi(0).RealDay Then
If k > 0 Then
If bf > SD(k - 1) Then SD(k) = bf: k = k + 1
Else
SD(0) = bf: k = 1
End If
End If
j = j + 1
Loop Until bf > yJD0 + 427
j = k: k = j - 1
'삭망월 변수를 초기화(삭망월 변수에 정삭일만 저장)
For i = 0 To 25
LD(i).StartDay = 0
LD(i).StartDay = SD(i)
LD(i).MonName = 100 '100은 아무 값도 지정되지 않았음을 나타냄
Next i
PreWinter = Junggi(1).RealDay '천정동지일
ThisWinter = Junggi(13).RealDay '계산하는 연도의 동지일
'입기시각과 정삭일을 비교해 삭망월 변수에 달 번호 매기기
idx1 = 0: idx2 = 0
For i = 0 To 24
LD(i).Junggi = False
For j = 0 To 15
If LD(i + 1).StartDay > Junggi(j).RealDay And Junggi(j).RealDay >= LD(i).StartDay Then
LD(i).Junggi = True '무중월인지 유중월인지 파악
If LD(i).MonName = 100 Then
LD(i).MonName = Junggi(j).MonNumber '중기에 따른 달 이름 넣기(초기값)
ElseIf Junggi(j).MonNumber = 11 Or LD(i).MonName = 11 Then '동짓달은 무조건 11월로 입력
LD(i).MonName = 11
End If
End If
Next j
Next i
'천정동지가 포함된 달과 계산하려는 해의 동짓달 사이에 포함된 달의 수 찾기
Count1 = 0
For i = 0 To k - 1
If PreWinter < LD(i).StartDay And LD(i).StartDay <= ThisWinter Then Count1 = Count1 + 1
If PreWinter < LD(i + 1).StartDay And LD(i).StartDay <= PreWinter Then idx1 = i 'idx1에 천정동지월의 변수번호 저장
If ThisWinter < LD(i + 1).StartDay And LD(i).StartDay <= ThisWinter Then idx2 = i 'idx2에 동지월의 변수번호 저장
Next i
'포함된 달의 개월수에 따라 치윤 시작(4개의 경우로 윤달의 형태 지정)
If Count1 = 12 Then
LeapType = 4 '조건 4. 천정동지월과 동지월 사이에 12개월이 있으면 이 사이의 달은 모두 평월.
Else '13개월이면 윤달이 있음.
If LD(idx1 + 1).Junggi = True And LD(idx1 + 2).Junggi = True Then LeapType = 1 '조건 1
If LD(idx1 + 1).Junggi = False And LD(idx1 + 2).Junggi = True Then LeapType = 2 '조건 2
If LD(idx1 + 1).Junggi = True And LD(idx1 + 2).Junggi = False Then LeapType = 3 '조건 3
'조건 1: 천정동지월 다음 2달이 모두 유중월, 평 12월과 평 1월임.
'조건 2: 천정동지월 다음 달은 무중월, 그 다음은 유중월, 윤 11월과 평 12월.
'조건 3: 천정동지월 다음 달이 유중월, 그 다음은 무중월, 평 12월과 윤 12월.
'여기서부터 윤달의 위치 추정
Leap13 = False
For i = (idx1 + 3) To (idx2 - 1) '(천정동지월+3개월)째부터 금년 동지월까지 검사
If LD(i).Junggi = False Then Leap13 = True '이 기간에 무중월이 있는지를 탐색
Next i
If LeapType = 2 Or LeapType = 3 Then Leap13 = False '조건 2와 3일 때는 이 기간동안 모두 평월임.
End If
'천정동지월에서 (천정동지월+2개월)까지 치윤, 월 번호 매기기.
LCount = 0
Select Case LeapType
Case 1, 4
LD(idx1 + 1).MonName = 12: LD(idx1 + 1).LYear = dYear - 1: LD(idx1 + 1).Junggi = True
LD(idx1 + 2).MonName = 1: LD(idx1 + 2).LYear = dYear: LD(idx1 + 2).Junggi = True
Case 2
LD(idx1 + 1).MonName = 11: LD(idx1 + 1).LYear = dYear - 1: LD(idx1 + 1).Junggi = False
LD(idx1 + 2).MonName = 12: LD(idx1 + 2).LYear = dYear - 1
Case 3
LD(idx1 + 1).MonName = 12: LD(idx1 + 1).LYear = dYear - 1
LD(idx1 + 2).MonName = 12: LD(idx1 + 2).LYear = dYear - 1: LD(idx1 + 2).Junggi = False
End Select
LD(idx1).MonName = 11: LD(idx1).LYear = dYear - 1
'(천정동지월+3개월)부터 동지월까지 치윤, 월 번호 매기기
fMON = 1: A = 0
If LeapType = 4 Then A = 1 '조건 4는 조건 1과 같은 방법으로 처리
For i = idx1 + 3 To idx2
LD(i).LYear = dYear
If LeapType = 1 Then '조건 1(또는 4)이면 첫번째 나오는 무중월을 윤달로 간주.
If LD(i).Junggi = True Or LCount > 0 Then
LD(i).Junggi = True
A = A + 1
Else
LCount = 1
End If
LD(i).MonName = fMON + A
Else '조건 2, 3이면 (천정동지월+3개월)부터 동지월까지는 모두 평월로 처리.
LD(i).MonName = fMON + A
LD(i).Junggi = True
A = A + 1
End If
Next i
For i = 0 To 24 '달 길이 계산
If Abs(LD(i + 1).StartDay - LD(i).StartDay) < 31 Then
LD(i).MonLength = LD(i + 1).StartDay - LD(i).StartDay
End If
Next i
For i = 0 To k - 1 '입력일이 포함된 달을 찾아 음력 날짜 출력
If jd0 >= LD(i).StartDay And jd0 < LD(i + 1).StartDay Then
LunarYear = LD(i).LYear
LunarMon = LD(i).MonName
LunarDay = jd0 - LD(i).StartDay + 1
IsLeap = Not LD(i).Junggi
Exit For
End If
Next i
End Sub
음력을 산출하는 구체적인 과정은 이 글에서 설명한대로 입니다. 추후에 실제 예를 들어가며 더욱 자세히 설명토록 하겠습니다.