; AHK版本: 		B:1.0.48.5 L:1.0.92.0
; 语言:			中文/English
; 平台:			Win7
; 作者:			海盗 <healthlolicon@gmail.com>
; 脚本类型:		函数
; 功能:			公历日期农历日期相互转换
; 缺陷:			只能查1899~2100年之间的年份

#NoEnv
/*
<参数>
Gregorian:
公历日期 格式 YYYYMMDD

<返回值>
农历日期 中文 天干地支属相
*/

MsgBox,% Date_GetLunarDate(20240419)

Date_GetLunarDate(Gregorian) {
  ;1899年~2100年农历数据
  ;前三位,Hex,转Bin,表示当年月份,1为大月,0为小月
  ;第四位,Dec,表示闰月天数,1为大月30天,0为小月29天
  ;第五位,Hex,转Dec,表示是否闰月,0为不闰,否则为闰月月份
  ;后两位,Hex,转Dec,表示当年新年公历日期,格式MMDD
  LunarData=
  (LTrim Join
  AB500D2,4BD0883,
  4AE00DB,A5700D0,54D0581,D2600D8,D9500CC,655147D,56A00D5,9AD00CA,55D027A,4AE00D2,
  A5B0682,A4D00DA,D2500CE,D25157E,B5500D6,56A00CC,ADA027B,95B00D3,49717C9,49B00DC,
  A4B00D0,B4B0580,6A500D8,6D400CD,AB5147C,2B600D5,95700CA,52F027B,49700D2,6560682,
  D4A00D9,EA500CE,6A9157E,5AD00D6,2B600CC,86E137C,92E00D3,C8D1783,C9500DB,D4A00D0,
  D8A167F,B5500D7,56A00CD,A5B147D,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,AD500D2,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,A6C147C,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
  )

  ;分解公历年月日
  StringLeft,Year,Gregorian,4
  StringMid,Month,Gregorian,5,2
  StringMid,Day,Gregorian,7,2
  if (Year>2100 Or Year<1900) {
    errorinfo=无效日期
    return,errorinfo
  }

  ;获取两年内的农历数据
  Pos:=(Year-1900)*8+1
  StringMid,Data0,LunarData,%Pos%,7
  Pos+=8
  StringMid,Data1,LunarData,%Pos%,7

  ;判断农历年份
  Analyze(Data1,MonthInfo,LeapInfo,Leap,Newyear)
  Date1=%Year%%Newyear%
  Date2:=Gregorian
  EnvSub,Date2,%Date1%,Days
  if (Date2<0) {					;和当年农历新年相差的天数
    Analyze(Data0,MonthInfo,LeapInfo,Leap,Newyear)
    Year-=1
    Date1=%Year%%Newyear%
    Date2:=Gregorian
    EnvSub,Date2,%Date1%,Days
  }
  ;计算农历日期
  Date2+=1
  LYear:=Year		;农历年份,就是上面计算后的值
  if Leap {			;有闰月
    StringLeft,p1,MonthInfo,%Leap%
    StringTrimLeft,p2,MonthInfo,%Leap%
    thisMonthInfo:=p1 . LeapInfo . p2
  }
  Else
    thisMonthInfo:=MonthInfo
  loop 13 {
    StringMid,thisMonth,thisMonthInfo,%A_index%,1
    thisDays:=29+thisMonth
    if Date2>%thisDays%
      Date2:=Date2-thisDays
    Else {
      if leap {
        if leap>%a_index%
          LMonth:=A_index
        Else
          LMonth:=A_index-1
      } Else
        LMonth:=A_index
      LDay:=Date2
      Break
    }
  }
  LDate=%LYear%年%LMonth%月%LDay%		;完成
;~ 	MsgBox,% LDate
  ;转换成习惯性叫法
  Tiangan=甲,乙,丙,丁,戊,已,庚,辛,壬,癸
  Dizhi=子,丑,寅,卯,辰,巳,午,未,申,酉,戌,亥
  Shengxiao=鼠,牛,虎,兔,龙,蛇,马,羊,猴,鸡,狗,猪
  loop,Parse,Tiangan,`,
    Tiangan%a_index%:=A_LoopField
  loop,Parse,Dizhi,`,
    Dizhi%a_index%:=A_LoopField
  loop,Parse,Shengxiao,`,
    Shengxiao%a_index%:=A_LoopField
  Order1:=Mod((LYear-4),10)+1
  Order2:=Mod((LYear-4),12)+1
  LYear:=Tiangan%Order1% . Dizhi%Order2% . "(" . Shengxiao%Order2% . ")"

  yuefen=正,二,三,四,五,六,七,八,九,十,十一,腊
  loop,Parse,yuefen,`,
    yuefen%A_index%:=A_LoopField
  LMonth:=yuefen%LMonth%

  rizi=初一,初二,初三,初四,初五,初六,初七,初八,初九,初十,十一,十二,十三,十四,十五,十六,十七,十八,十九,二十,廿一,廿二,廿三,廿四,廿五,廿六,廿七,廿八,廿九,三十
  loop,Parse,rizi,`,
    rizi%A_index%:=A_LoopField
  LDay:=rizi%LDay%

  LDate=%LYear%年%LMonth%月%LDay%
  Return LDate
}

/*
<参数>
Lunar:
农历日期
IsLeap:
是否闰月
如,某年闰7月,第一个7月不是闰月,第二个7月是闰月,IsLeap=1
当年没有闰月这个参数无效

<返回值>
公历日期(YYYYDDMM)
*/
Date_GetDate(Lunar,IsLeap=0) {
  ;分解农历年月日
  StringLeft,Year,Lunar,4
  StringMid,Month,Lunar,5,2
  StringRight,Day,Lunar,2
  if substr(Month,1,1)=0
    StringTrimLeft,month,month,1
  if (Year>2100 Or Year<1900 or Month>12 or Month<1 or Day>30 or Day<1) {
    errorinfo=无效日期
    return errorinfo
  }

  ;1899年~2100年农历数据
  ;前三位,Hex,转Bin,表示当年月份,1为大月,0为小月
  ;第四位,Dec,表示闰月天数,1为大月30天,0为小月29天
  ;第五位,Hex,转Dec,表示是否闰月,0为不闰,否则为闰月月份
  ;后两位,Hex,转Dec,表示当年新年公历日期,格式MMDD
  LunarData=
  (LTrim Join
  AB500D2,4BD0883,
  4AE00DB,A5700D0,54D0581,D2600D8,D9500CC,655147D,56A00D5,9AD00CA,55D027A,4AE00D2,
  A5B0682,A4D00DA,D2500CE,D25157E,B5500D6,56A00CC,ADA027B,95B00D3,49717C9,49B00DC,
  A4B00D0,B4B0580,6A500D8,6D400CD,AB5147C,2B600D5,95700CA,52F027B,49700D2,6560682,
  D4A00D9,EA500CE,6A9157E,5AD00D6,2B600CC,86E137C,92E00D3,C8D1783,C9500DB,D4A00D0,
  D8A167F,B5500D7,56A00CD,A5B147D,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,AD500D2,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,A6C147C,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
  )

  ;获取当年农历数据
  Pos:=(Year-1899)*8+1
  StringMid,Data,LunarData,%Pos%,7

  ;判断公历日期
  Analyze(Data,MonthInfo,LeapInfo,Leap,Newyear)
  ;计算到当天到当年农历新年的天数
  Sum := 0
  if Leap {			;有闰月
    StringLeft,p1,MonthInfo,%Leap%
    StringTrimLeft,p2,MonthInfo,%Leap%
    thisMonthInfo:=p1 . LeapInfo . p2
    if (Leap!=Month and IsLeap=1) {
      errorinfo=该月不是闰月
      return,errorinfo
    }
    if (Month<=Leap and IsLeap=0) {
      loop,% Month-1 {
        StringMid,thisMonth,thisMonthInfo,%A_index%,1
        Sum:=Sum+29+thisMonth
      }
    } Else {
      loop % Month {
        StringMid,thisMonth,thisMonthInfo,%A_index%,1
        Sum:=Sum+29+thisMonth
      }
    }
  } Else {
    loop % Month-1 {
      thisMonthInfo:=MonthInfo
      StringMid,thisMonth,thisMonthInfo,%A_index%,1
      Sum:=Sum+29+thisMonth
    }
  }
  Sum:=Sum+Day-1

  GDate=%Year%%NewYear%
  GDate+=%Sum%,days
  StringTrimRight,Gdate,Gdate,6
  return Gdate
}

; 分析农历数据的函数 按上面所示规则分析
; 4个回参分别对应四项
Analyze(Data, ByRef rtn1, ByRef rtn2, ByRef rtn3, ByRef rtn4) {
  ;rtn1
  StringLeft,Month,Data,3
  rtn1:=System("0x" . Month,"H","B")
  if Strlen(rtn1)<12
    rtn1:="0" . rtn1

  ;rtn2
  StringMid,rtn2,Data,4,1

  ;rtn3
  StringMid,leap,Data,5,1
  rtn3:=System("0x" . leap,"H","D")

  ;rtn4
  StringRight,Newyear,Data,2
  rtn4:=System("0x" . newyear,"H","D")
  if strlen(rtn4)=3
    rtn4:="0" . rtn4
}

; 引用库
Bin(x) {         ;dec-bin
  while x
  r:=1&x r,x>>=1
  return r
}

Dec(x) {     ; bin-dec
  b:=StrLen(x),r:=0
  loop,parse,x
  r|=A_LoopField<<--b
  return r
}

Dec_Hex(x) {      ; dec-hex
  SetFormat, IntegerFast, hex
  he := x
  he += 0
  he .= ""
  SetFormat, IntegerFast, d
  Return,he
}

Hex_Dec(x) {
  SetFormat, IntegerFast, d
  de := x
  de := de + 0
  Return,de
}

system(x,InPutType="D",OutPutType="H") {
  if (InputType="B") {
    if (OutPutType="D")
      r:=Dec(x)
    Else if (OutPutType="H") {
      x:=Dec(x)
      r:=Dec_Hex(x)
    }
  } Else if (InputType="D") {
    if (OutPutType="B")
      r:=Bin(x)
    Else if (OutPutType="H")
      r:=Dec_Hex(x)
  } Else if (InputType="H") {
    if (OutPutType="B") {
      x:=Hex_Dec(x)
      r:=Bin(x)
    } Else if (OutPutType="D")
      r:=Hex_Dec(x)
  }
  Return r
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。