找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5701|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

關(guān)于網(wǎng)上公歷轉(zhuǎn)農(nóng)歷模塊中的一點錯誤

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:55874 發(fā)表于 2013-10-14 00:15 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式


從網(wǎng)上下載公歷轉(zhuǎn)農(nóng)歷模塊并應(yīng)用于公歷轉(zhuǎn)換農(nóng)歷,覺得轉(zhuǎn)換速度極快的,很實用。公歷轉(zhuǎn)農(nóng)歷模塊的源碼作者的確是高手!但最近發(fā)現(xiàn)一個小錯誤,就是在今年(2013年)的6月中旬公歷轉(zhuǎn)換成農(nóng)歷時好像要差一天,如今天是6月18日,農(nóng)歷是五月十一,可是用此模塊轉(zhuǎn)換出來的農(nóng)歷卻是五月初十,差了一天。

源碼中作者有具體說明十六進制的農(nóng)歷常量的編寫方法,本人根據(jù)說明,確定原因是2013的農(nóng)歷四月份被作者設(shè)置成大月,而實際是小月,于是動手將2013年的四月設(shè)置成小月,即農(nóng)歷常量中的B5500D2改成A5500D2,問題終于得到解決。下面是正確的源碼:



Option Explicit



'公歷轉(zhuǎn)農(nóng)歷模塊

'原創(chuàng):互聯(lián)網(wǎng)

'修正:阿勇 2005/1/12  
       '再修正:揭陽新新科技  2013/6/18



'// 農(nóng)歷數(shù)據(jù)定義 //

'先以 H2B 函數(shù)還原成長度為 18 的字符串,其定義如下:

'前12個字節(jié)代表1-12月:1為大月,0為小月;壓縮成十六進制(1-3位)

'第13位為閏月的情況,1為大月30天,0為小月29天;(4位)

'第14位為閏月的月份,如果不是閏月為0,否則給出月份(5位)

'最后4位為當(dāng)年農(nóng)歷新年的公歷日期,如0131代表1月31日;當(dāng)作數(shù)值轉(zhuǎn)十六進制(6-7位)



'農(nóng)歷常量(1899~2100,共202年)

Private Const ylData = "AB500D2,4BD0883," _

        & "4AE00DB,A5700D0,54D0581,D2600D8,D9500CC,655115D,56A00D5,9AD00CA,55D027A,4AE00D2," _

        & "A5B0682,A4D00DA,D2500CE,D25157E,B5500D6,56A00CC,ADA027B,95B00D3,49717C9,49B00DC," _

        & "A4B00D0,B4B0580,6A500D8,6D400CD,AB5115C,2B600D5,95700CA,52F027B,49700D2,6560682," _

        & "D4A00D9,EA500CE,6A9157E,5AD00D6,2B600CC,86E137C,92E00D3,C8D1783,C9500DB,D4A00D0," _

        & "D8A167F,B5500D7,56A00CD,A5B115D,25D00D5,92D00CA,D2B027A,A9500D2,B550781,6CA00D9," _

        & "B5500CE,535157F,4DA00D6,A5B00CB,457037C,52B00D4,A9A0883,E9500DA,6AA00D0,AEA0680," _

        & "AB500D7,4B600CD,AAE047D,A5700D5,52600CA,F260379,D9500D1,5B50782,56A00D9,96D00CE," _

        & "4DD057F,4AD00D7,A4D00CB,D4D047B,D2500D3,D550883,B5400DA,B6A00CF,95A1680,95B00D8," _

        & "49B00CD,A97047D,A4B00D5,B270ACA,6A500DC,6D400D1,AF40681,AB600D9,93700CE,4AF057F," _

        & "49700D7,64B00CC,74A037B,EA500D2,6B50883,5AC00DB,AB600CF,96D0580,92E00D8,C9600CD," _

        & "D95047C,D4A00D4,DA500C9,755027A,56A00D1,ABB0781,25D00DA,92D00CF,CAB057E,A9500D6," _

        & "B4A00CB,BAA047B,A5500D2,55D0983,4BA00DB,A5B00D0,5171680,52B00D8,A9300CD,795047D," _

        & "6AA00D4,AD500C9,5B5027A,4B600D2,96E0681,A4E00D9,D2600CE,EA6057E,D5300D5,5AA00CB," _

        & "76A037B,96D00D3,4AB0B83,4AD00DB,A4D00D0,D0B1680,D2500D7,D5200CC,DD4057C,B5A00D4," _

        & "56D00C9,55B027A,49B00D2,A570782,A4B00D9,AA500CE,B25157E,6D200D6,ADA00CA,4B6137B," _

        & "93700D3,49F08C9,49700DB,64B00D0,68A1680,EA500D7,6AA00CC,A6C115C,AAE00D4,92E00CA," _

        & "D2E0379,C9600D1,D550781,D4A00D9,DA400CD,5D5057E,56A00D6,A6C00CB,55D047B,52D00D3," _

        & "A9B0883,A9500DB,B4A00CF,B6A067F,AD500D7,55A00CD,ABA047C,A5A00D4,52B00CA,B27037A," _

        & "69300D1,7330781,6AA00D9,AD500CE,4B5157E,4B600D6,A5700CB,54E047C,D1600D2,E960882," _

        & "D5200DA,DAA00CF,6AA167F,56D00D7,4AE00CD,A9D047D,A2D00D4,D1500C9,F250279,D5200D1"



Private Const ylMd0 = "初一初二初三初四初五初六初七初八初九初十十一十二十三十四十五" _

        & "十六十七十八十九二十廿一廿二廿三廿四廿五廿六廿七廿八廿九三十 "



Private Const ylMn0 = "正二三四五六七八九十冬臘"

Private Const ylTianGan0 = "甲乙丙丁戊已庚辛壬癸"

Private Const ylDiZhi0 = "子丑寅卯辰巳午未申酉戌亥"

Private Const ylShu0 = "鼠;⑼谬埳唏R羊猴雞狗豬"



'公歷日期轉(zhuǎn)農(nóng)歷

Function GetYLDate(ByVal strDate As String) As String



On Error GoTo aErr



    If Not IsDate(strDate) Then Exit Function



    Dim setDate As Date, tYear As Integer, tMonth As Integer, tDay As Integer

    setDate = CDate(strDate)

    tYear = Year(setDate): tMonth = Month(setDate): tDay = Day(setDate)



    '如果不是有效有日期,退出

    If tYear > 2100 Or tYear < 1900 Then Exit Function



    Dim daList() As String * 18, conDate As Date, thisMonths As String

    Dim AddYear As Integer, AddMonth As Integer, AddDay As Integer, getDay As Integer

    Dim YLyear As String, YLShuXing As String

    Dim dd0 As String, mm0 As String, ganzhi(0 To 59) As String * 2

    Dim RunYue As Boolean, RunYue1 As Integer, mDays As Integer, i As Integer



    '加載2年內(nèi)的農(nóng)歷數(shù)據(jù)

    ReDim daList(tYear - 1 To tYear)

    daList(tYear - 1) = H2B(Mid(ylData, (tYear - 1900) * 8 + 1, 7))

    daList(tYear) = H2B(Mid(ylData, (tYear - 1900 + 1) * 8 + 1, 7))



    AddYear = tYear



initYL:



    AddMonth = CInt(Mid(daList(AddYear), 15, 2))

    AddDay = CInt(Mid(daList(AddYear), 17, 2))

    conDate = DateSerial(AddYear, AddMonth, AddDay)     '農(nóng)歷新年日期



    getDay = DateDiff("d", conDate, setDate) + 1        '相差天數(shù)

    If getDay < 1 Then AddYear = AddYear - 1: GoTo initYL



    thisMonths = Left(daList(AddYear), 14)

    RunYue1 = Val("&H" & Right(thisMonths, 1))           '閏月月份

    If RunYue1 > 0 Then                                  '有閏月

        thisMonths = Left(thisMonths, RunYue1) & Mid(thisMonths, 13, 1) & Mid(thisMonths, RunYue1 + 1)

    End If

    thisMonths = Left(thisMonths, 13)



    For i = 1 To 13                                      '計算天數(shù)

        mDays = 29 + CInt(Mid(thisMonths, i, 1))

        If getDay > mDays Then

            getDay = getDay - mDays

        Else

            If RunYue1 > 0 Then

                If i = RunYue1 + 1 Then RunYue = True

                If i > RunYue1 Then i = i - 1

            End If



            AddMonth = i

            AddDay = getDay

            Exit For

        End If

    Next



    dd0 = Mid(ylMd0, (AddDay - 1) * 2 + 1, 2)

    mm0 = Mid(ylMn0, AddMonth, 1) + "月"



    For i = 0 To 59

        ganzhi(i) = Mid(ylTianGan0, (i Mod 10) + 1, 1) + Mid(ylDiZhi0, (i Mod 12) + 1, 1)

    Next i



    YLyear = ganzhi((AddYear - 4) Mod 60)

    YLShuXing = Mid(ylShu0, ((AddYear - 4) Mod 12) + 1, 1)

    If RunYue Then mm0 = "閏" & mm0



    GetYLDate = "農(nóng)歷" & YLyear & "(" & YLShuXing & ")年" & mm0 & dd0



aErr:



End Function





'農(nóng)歷轉(zhuǎn)公歷日期

'secondMonth 為真,則天示當(dāng) tMonth 是閏月時,取第二個月

Function GetDate(ByVal tYear As Integer, tMonth As Integer, tDay As Integer, Optional secondMonth As Boolean = False) As String



On Error GoTo aErr



    If tYear > 2100 Or tYear < 1899 Or tMonth > 12 Or tMonth < 1 Or tDay > 30 Or tDay < 1 Then Exit Function



    Dim thisMonths As String, ylNewYear As Date, toMonth As Integer

    Dim mDays As Integer, RunYue1 As Integer, i As Integer

    thisMonths = H2B(Mid(ylData, (tYear - 1899) * 8 + 1, 7))



    If tDay > 29 + CInt(Mid(thisMonths, tMonth, 1)) Then Exit Function



    ylNewYear = DateSerial(tYear, CInt(Mid(thisMonths, 15, 2)), CInt(Mid(thisMonths, 17, 2)))     '農(nóng)歷新年日期



    thisMonths = Left(thisMonths, 14)

    RunYue1 = Val("&H" & Right(thisMonths, 1))           '閏月月份



    toMonth = tMonth - 1

    If RunYue1 > 0 Then                                  '有閏月

        thisMonths = Left(thisMonths, RunYue1) & Mid(thisMonths, 13, 1) & Mid(thisMonths, RunYue1 + 1)

        If tMonth > RunYue1 Or (secondMonth And tMonth = RunYue1) Then toMonth = tMonth

    End If

    thisMonths = Left(thisMonths, 13)



    mDays = 0

    For i = 1 To toMonth

        mDays = mDays + 29 + CInt(Mid(thisMonths, i, 1))

    Next

    mDays = mDays + tDay



    GetDate = ylNewYear + mDays - 1



aErr:



End Function



'將壓縮的陰歷字符還原

Private Function H2B(ByVal strHex As String) As String

    Dim i As Integer, i1 As Integer, tmpV As String

    Const hStr = "0123456789ABCDEF"

    Const bStr = "0000000100100011010001010110011110001001101010111100110111101111"



    tmpV = UCase(Left(strHex, 3))



    '十六進制轉(zhuǎn)二進制

    For i = 1 To Len(tmpV)

        i1 = InStr(hStr, Mid(tmpV, i, 1))

        H2B = H2B & Mid(bStr, (i1 - 1) * 4 + 1, 4)

    Next



    H2B = H2B & Mid(strHex, 4, 2)



    '十六進制轉(zhuǎn)十進制

    H2B = H2B & "0" & CStr(Val("&H" & Right(strHex, 2)))

End Function

       在此再次感謝原作者的艱辛勞動和無私奉獻 !


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表