zoukankan      html  css  js  c++  java
  • 公历转干支历lua实现

        干支纪日是现今历史上最长的纪日法,也是中国特有的历法,据考从伏羲氏就开始有创建,从中国古代的夏朝就已经开始使用。我国的干支纪日,从鲁隐公三年二月己巳日(公元前720年2月10日)开始,一直到今天,都未曾间断。
        干支历采用六十甲子循环记载年月日时的信息,干支历的年月信息,与公历、农历的年不同,是以节气为根据的,就是根据地球与太阳的旋转角度精确计算的,干支历中,每年以立春作为开始,每月以节气中的节开始,立春为一月,惊蛰为二月,依次类推.
        干支历中,月份的地支排列是:一月建寅,二月建卯,... 十一月建子,十二月建丑,时辰的地支排列是:子、丑、寅、... 、戌、亥
    关于推断月干和时干的信息,古人为了方便记忆,有口诀流传下来,可以根据年干推断月干,根据日干推断时干,推月干的称为“五虎遁元诀", 推时干的称为"五鼠遁元诀", 虎和鼠的称谓来源于地支对应的十二生肖,而今人多直接称为”年上起月诀“和”日上起时诀".

    五虎遁元诀:
    甲己之年丙作首
    乙庚之年戊为头
    丙辛之岁寻庚上
    丁壬壬寅顺水流
    若问戊癸何方发
    甲寅之上好追求

    五鼠遁元诀:
    甲己还加甲
    乙庚丙作初
    丙辛从戊起
    丁壬庚子居
    戊癸何方发

    实现这个公历转干支历算法用到的节气计算部分的代码,见我前面的一篇文章:寿星万年历---Lua实现

    以下是公历转干支历的lua实现:

    --公历转干支历实现
    --[[干支历的年以立春发生时刻(注意,不是立春日的0时)为年干支的起点;各月干支以十二节时刻(注意,不一定是各节气日的0时)
    --]]
    --require('common')
    require('jieqi')
    
    GanZhiLi = {
    }
    
    --创建干支历对象
    function GanZhiLi:new()
        local o = {}
        setmetatable(o, self)
        self.__index = self
        o:setTime(os.time())
        return o
    end
    
    --将offset的数值转化为特定偏移下的周期数,起始数,偏移量,周期
    function GanZhiLi:calRound(start, offset, round)
        if start > round or start <=0 then return nil end --参数不对
        offset = math.floor(math.fmod(start+offset, round))
        if offset >=0 then
            if offset==0 then offset=round end
            return offset
        else
            return round + offset
        end
    end
    
    --周期循环数
    function calR2(n, round)
        local x = math.floor(math.fmod(n,round))
        if x==0 then x=round end
        return x
    end
    
    --设置用于转换干支历的公历时间
    function GanZhiLi:setTime(t)
        self.ttime = t
        self.tday = os.date('*t', t)
        --for k,v in pairs(self.tday) do
        --    print(k,v)
        --end
        --先取公历今年的干支
        self.jqs = getYearJQ(self.tday.year)
        self.ganZhiYearNum = self:calGanZhiYearNum()
        if self.ganZhiYearNum ~= self.tday.year then
            --如果在节气上还没到今年的立春,则还没到干支历的今年,需要取干支历的年份的24节气
            self.jqs = getYearJQ(self.ganZhiYearNum)
        end
        self.ganZhiMonNum = self:calGanZhiMonthNum()
        self.curJq = self:getCurJQ()
    
    end
    
    function GanZhiLi:getCurJQ()
        --for i=1,24 do
        --    local x = os.date('*t', self.jqs[i])
        --    print(x.year, x.month, x.day, x.hour, x.min, x.sec)
        --end
        local x = 0
        if self.ttime < self.jqs[1] then return nil end --出错,计算错年了?
        for i=1,23 do
            if self.jqs[i] <= self.ttime and self.jqs[i+1] > self.ttime then x=i break end
        end
        if x==0 then x=24 end
        return x --返回以立春为起始序号1的节气
    end
    
    
    --根据公历年份和节气计算干支历的年份
    function GanZhiLi:calGanZhiYearNum()
        if (self.ttime < self.jqs[1]) then return self.tday.year -1
        else return self.tday.year end
    end
    
    --获取干支月份
    function GanZhiLi:calGanZhiMonthNum()
        if self.ttime < self.jqs[1] then return nil end
        local x = 0
        if self.ttime < self.jqs[1] then return nil end --出错,计算错年了?
        for i=1,23 do
            if self.jqs[i] <= self.ttime and self.jqs[i+1] > self.ttime then x=i end
        end
        if x==0 then x=24 end
        return math.floor((x+1)/2)
    end
    
    
    --返回年的干支序号,1为甲子。。。
    function GanZhiLi:getYearGanZhi()
        local jiaziYear = 1984 --甲子年
        --print(self.ganZhiYearNum)
        local yeardiff = self.ganZhiYearNum - jiaziYear
        return self:calRound(1,yeardiff,60)
    end
    
    --返回年的天干号,1为甲
    function GanZhiLi:getYearGan()
        local idx = self:getYearGanZhi()
        return self:calR2(idx,10)
    end
    
    --返回年的地支号,1为子
    function GanZhiLi:getYearZhi()
        local idx = self:getYearGanZhi()
        return self:calR2(idx,12)
    end
    
    --返回月的干支号
    function GanZhiLi:getMonGanZhi()
        local ck ={year=2010,month=2,day=4,hour=6,min=42,sec=0}
        local x = os.time(ck) --参考月,立春时间2010-2-4 6:42:00对应的干支序号为15
        local ydiff = self.ganZhiYearNum - ck.year
        local mdiff = self.ganZhiMonNum-1
        if ydiff >=0 then
            mdiff = ydiff*12 + mdiff
        else
            mdiff = (ydiff+1)*12 + mdiff -12
        end
        return self:calRound(15,mdiff, 60)
    end
    
    
    function GanZhiLi:getMonGan()
        local idx = self:getMonGanZhi()
        return self:calR2(idx,10)
    end
    
    function GanZhiLi:getMonZhi()
        local idx = self:getMonGanZhi()
        return self:calR2(idx,12)
    end
    
    --返回日的干支号,甲子从1开始
    function GanZhiLi:getDayGanZhi()
        local DAYSEC = 24*3600
        local jiaziDayTime = os.time({year=2012, month=8, day=30, hour=23, min=0,sec=0})
        local daydiff = math.floor((self.ttime - jiaziDayTime)/DAYSEC)
        return self:calRound(1,daydiff,60)
    end
    
    --返回日的天干号
    function GanZhiLi:getDayGan()
        local idx = self:getDayGanZhi()
        return self:calR2(idx,10)
    end
    
    --返回日的地支号
    function GanZhiLi:getDayZhi()
        local idx = self:getDayGanZhi()
        return self:calR2(idx,12)
    end
    
    --返回时辰的干支号
    function GanZhiLi:getHourGanZhi()
        local SHICHENSEC=3600*2
        local jiaziShiTime = os.time({year=2012, month=8, day=30, hour=23, min=0, sec=0})
        local shiDiff = math.floor((self.ttime - jiaziShiTime)/SHICHENSEC)
        return self:calRound(1,shiDiff,60)
    end
    
    --返回时干号
    function GanZhiLi:getShiGan()
        local idx = self:getHourGanZhi()
        return self:calR2(idx,10)
    end
    
    --返回时支号
    function GanZhiLi:getShiZhi()
        local idx = self:getHourGanZhi()
        return self:calR2(idx,12)
    end
    
    
    
    
    
    --====================以下是测试代码=============
    
    local jqB={ --节气表
    "立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露",
    "秋分","寒露","霜降","立冬","小雪","大雪","冬至","小寒","大寒",}
    --天干
    local tiangan = {'', '', '', '', '', '', '', '', '', ''}
    
    --地支
    local dizhi = {'', '', '', '', '', '', '', '', '', '', '', ''}
    
    
    --根据六十甲子序号,返回六十甲子字符串,甲子从1开始
    local function get60JiaZiStr(i)
    local gan = i % 10
            if gan == 0  then gan = 10 end
            local zhi = i % 12
            if zhi == 0 then zhi = 12 end
            return tiangan[gan]..dizhi[zhi]
    end
    
    
    
    --测试
    x = GanZhiLi:new()
    x:setTime(os.time({year=2000,month=11, day=22,hour=12,min=4,sec=5}))
    --x:setTime(os.time())
    yidx = x:getYearGanZhi()
    midx = x:getMonGanZhi()
    didx = x:getDayGanZhi()
    hidx = x:getHourGanZhi()
    print('干支:'  .. get60JiaZiStr(yidx) .. ' ' .. get60JiaZiStr(midx) .. ' ' .. get60JiaZiStr(didx) .. ' ' .. get60JiaZiStr(hidx))
    print('干支年份:' .. x.ganZhiYearNum .. ', 干支月份' .. x.ganZhiMonNum .. ', 当前节气:' .. jqB[x.curJq] )
  • 相关阅读:
    关于证书
    title向左_右滚动效果
    js标题滚动效果
    js小结
    javascript数组以及对象
    javascript数据类型转换
    javascript变量作用域
    sqlldr
    java 配置文件读取
    hbase 协处理器
  • 原文地址:https://www.cnblogs.com/moodlxs/p/2694743.html
Copyright © 2011-2022 走看看