摘要:取名讲究五行平衡,生辰八字,五行归属,年月日时四柱如何计算?本文主要实现基于Python的纳音五行测算,解释程序设计思路以及五行测算算法。

一、引言

  人们常说生辰八字,是如何测算的?有了生辰八字,如何测试五行归属,网上测试方法五花八门,结果并不统一,通过调研现实师父,调研收集比较一致的生辰和五行测算算法,基于Python开发。

二、天干地支

  生辰八字,即对于一个人的出生年月日和时辰,称为四柱,分别为年柱、月柱、日柱和时柱,各自分别对应一个天干和地支,共计八个字,故称八字。
  天干地支,简称干支,古代常用于纪年、纪月、纪日和纪时。如甲午中日战争,是指19世纪末日本侵略中国和朝鲜的战争,按中国干支纪年,战争爆发的1894年为甲午年,故称甲午战争。
  干支源自中国远古时代对天象的观测。十天干是指“甲、乙、丙、丁、戊、己、庚、辛、壬、癸”,十二地支是指“子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥”。按照组合,十天干和十二地支依次相配,组成六十个基本单位,两者间按固定顺序相互配合,组成了干支纪元法。干支纪元法六十年一循环,故人们常称六十年为一甲子。本文主要讨论生辰的干支计算以及五行归属。

三、五行

  五行,也叫五行学说,是认识世界的基本方式, 即常说的金木水火土,是中国古代哲学家用五行理论来说明世界万物的形成及其相互关系。它强调整体,旨在描述事物的运动形式以及转化关系。阴阳是古代的对立统一学说,五行是原始的系统论。五行有相生相克之说:
  相生,是指两类属性不同的事物之间存在相互帮助,相互促进的关系;具体是:木生火,火生土,土生金,金生水,水生木。
  相克,则与相生相反,是指两类不同五行属性事物之间关系是相互克制的;具体是:木克土,土克水,水克火、火克金、金克木。

  1.正五行

  何为正五行,是和纳音五行相对,正五行是指天干和地支对应的五行。
  十天干五行:甲乙为木,丙丁为火,戊己为土,庚辛为金,壬癸为水。
  十二地支五行:子为水,丑为土,寅卯为木,辰为土,巳午为火,未为土,申酉为金,戌为火,亥为水。
  例如生辰八字:‘癸卯’, ‘己未’, ‘丁丑’, '丙午‘,对应的五行为:水木,土土,火土,火火。

  2.纳音五行

  天干有天干的五行,地支有地支的五行,天干与地支配合后会变成新的五行,称为“纳音五行”,原干支五行称为正五行,纳音五行叫做假借五行,因为它是假借古代五音(宫商角徵羽)和十二音律而组合成的纳音五行。
  在实际中使用正五行常与实际有出入,于是便用纳音做了补充,两者之间的关系可以看做是正五行为经,纳音五行为纬。这解释了农历2023年为什么既有人说是水兔年,又有人说为金兔年。网上查询偏水兔的较多,农历2023年的年柱为‘癸卯’,天干对于为水,故称“水兔”(实在不懂为啥这里不管地支);实际在民间,农历2023年的年柱为‘癸卯’,使用纳音五行,对应纳音为“金箔金”,故称“金兔”(参考中华万年历,对每日日柱五行,使用的便是纳音五行)。
  纳音五行主要用于推算吉凶祸福、预测运势以及起名等方面(咱不迷信,只为搞清日历计算方法)。
  六十甲子纳音表五行歌:

甲子、乙丑——海中金,丙寅、丁卯——炉中火。
戊辰、己巳——大林木,庚午、辛未——路旁土。
壬申、癸酉——剑锋金,甲戌、乙亥——山头火。
丙子、丁丑——涧下水,戊寅、己卯——城头土。
庚辰、辛巳——白蜡金,壬午、癸未——杨柳木。
甲申、乙酉——泉中水,丙戌、丁亥——屋上土。
戊子、己丑——霹雳火,庚寅、辛卯——松柏木。
壬辰、癸巳——长流水,甲午、乙未——沙中金。
丙申、丁酉——山下火,戊戌、己亥——平地木。
庚子、辛丑——壁上土,壬寅、癸卯——金箔金。
甲辰、乙巳——覆灯火,丙午、丁未——天河水。
戊申、己酉——大驿土,庚戌、辛亥——钗钏金。
壬子、癸丑——桑柘木,甲寅、乙卯——大溪水。
丙辰、丁巳——沙中土,戊午、己未——天上火。
庚申、辛酉——石榴木,壬戌、癸亥——大海水。

  农历2023年的年柱为‘癸卯’,对照纳音五行,五行为“金箔金”,故称农历2023年为“金兔“”年。

四、程序设计思路

  生辰八字的计算算的是农历,故首先需实现公历和农历的转换,计算出了农历之后,再依次实现年柱、月柱、日柱和时柱的计算。

  1.公历和农历转换

  公历和农历的转换使用第三方库zhdate,使用pip安装:

pip install zhdate

  zhdate实现了不用网络接口直接本地计算中国农历,支持农历公历互转,支持计算的农历时间范围为1900年至2100年,实现的基本思路是内置了从1900年至2100年每年的农历春节的公历日期和从1900年到2100年的农历月份数据代码(包括是否闰年、12个月份数的大小情况),作为农历和公历互转的基本知识库,通过计算当前农历日期和当年农历新年之间的天数差值,进一步实现农历和公历的互转,更详细的实现请直接阅读源码。

from datetime import datetime
from zhdate import ZhDate# 农历转公历
lunar_date = ZhDate(2023, 6, 1)  # 新建农历
print(lunar_date)  # 查看农历
dt_date = lunar_date .to_datetime() # 农历转换成阳历日期datetime 类型
print(dt_date)# 公历转农历
dt_date = datetime(2023, 7, 18)
lunar_date = ZhDate.from_datetime(dt_date)
print(lunar_date)

  执行结果:

  2.年柱算法与实现

  年柱计算算法使用农历年,例如2023年1月18日,农历为2022年,应代入2022年进行计算,网上不少算法是直接使用2023年计算的,这回答了为什么要首先实现1.公历和农历转换。
  的具体计算公式如下:

g = (year -3) % 10 - 1
d = (year -3) % 12 - 1

  年份减3(干支纪年法是从公元4年开始的)除以10取余,余数为天干的字,年份减3除以12取余,余数为地支的字,这样合起来变成了该年的年柱。需注意的是,天干的计算结果为1-10(相应的地支计算结果为1-12),取余后分别为1-9及0,0表示的应该是第10个天干或者第12个地支,在Python中字符串或者列表是从0开始计算的,这样恰造成计算的天干或者地支恰好错一位,故计算出来的1应该表示的是第1个天干或者地支,其索引为0,故减1实现,对于第10个天干或者地支,表示取最后一个天干或者地支,取余结果为0,减1为-1,在Python中有倒序索引,此时取最后一个元素。
  年份天干计算实现代码如下:

def __cal_year_ganzhi(self):# 计算年份的天干地支gan = TIANGAN[(self.lunar_datetime.year - 3) % 10 - 1]zhi = DIZHI[(self.lunar_datetime.year - 3) % 12 - 1]return gan + zhi

  3.月柱算法与实现

  一年12个月,有12个地支,故每月和地支的关系是固定的,但并不是每月的农历初一为新的地支开始,其和24节气中的节律相关,因此月柱计算算法相比年柱计算较为复杂,网上不少算法计算有误差,并没有按照节律来计算月柱。

    (1).地支算法

  具体来说按照12节律的顺序:‘立春’, ‘惊蛰’, ‘清明’, ‘立夏’, ‘芒种’, ‘小暑’, ‘立秋’, ‘白露’, ‘寒露’, ‘立冬’, ‘大雪’,‘小寒’,分别对应寅、卯、辰、巳、午、未、申、酉、戌、亥、子、丑;每个节律开始的第一天到下一个节律的前一天,均为对应的地支关系。
  故月柱地支的计算问题转换为十二节律的计算问题,十二节律的计算公式为:

int(year % 100 * 0.2422 + values[c] - (year % 100 - 1) // 4)

  年数的后2位乘0.2422加该节律对应的C值,并减去闰年数,不同节律的C值及具体映射关系通过字典的形式给出。其中,节律为key,对应月份和C值构成列表为value,列表第一个元素为节律对应的公历月份,其余为该节律对应的C值,C值有两个分别表示对应的20世纪和21世纪的节律C值,一个的表示20世纪和21世纪节律C值相同。
  节律日期月份及C值字段如下:

MONTH_C = {"立春": [2, 3.87],"惊蛰": [3, 5.63],"清明": [4, 5.59, 4.81],"立夏": [5, 6.318, 5.52],"芒种": [6, 6.5, 5.678],"小暑": [7, 7.928, 7.108],"立秋": [8, 8.35, 7.5],"白露": [9, 8.44, 7.646],"寒露": [10, 9.098, 8.318],"立冬": [11, 8.218, 7.438],"大雪": [12, 7.9, 7.18],"小寒": [1, 6.11, 5.4055]
}

    (2).天干算法

  月份天干计算比较简单,使用公历年进行计算:

g = ((year % 5 - 2) * 2 - 1 + 10) % 10 - 1

  公历年份除以5的余数减2后乘以2再减1,当该数是负数时加10,最后减1和前面类似,因为Python中的索引从0开始。

    (3).代码实现

def __cal_month_ganzhi(self):# 计算月份的天干地支year, month, day = self.datetime.year, self.datetime.month, self.datetime.daycur_date = datetime(year, month, day)gan_index = ((year % 5 - 2) * 2 - 1 + 10) % 10 - 1for i in range(len(MONTHS)):if cur_date < self.month_dates[MONTHS[i]]:return TIANGAN[(gan_index + i - 2 + 10) % 10] + DIZHI[i]

  4.日柱算法与实现

  日柱的算法暂未找到有效的计算公式,从zhdate公历农历转换处得来的灵感,通过内置的1900年到2100年每年第一天(即元旦日的干支),通过计算具体计算日与元旦的天数差推导出实际的干支,每年元旦日干支字典如下:

YUNDAN_GANZHI = {'1900': '甲戌', '1901': '己卯', '1902': '甲申', '1903': '己丑', '1904': '甲午', '1905': '庚子', '1906': '乙巳', '1907': '庚戌',        '1908': '乙卯', '1909': '辛酉', '1910': '丙寅', '1911': '辛未', '1912': '丙子', '1913': '壬午', '1914': '丁亥', '1915': '壬辰', '1916': '丁酉', '1917': '癸卯', '1918': '戊申', '1919': '癸丑', '1920': '戊午', '1921': '甲子', '1922': '己巳', '1923': '甲戌', '1924': '己卯', '1925': '乙酉', '1926': '庚寅', '1927': '乙未', '1928': '庚子', '1929': '丙午', '1930': '辛亥', '1931': '丙辰', '1932': '辛酉', '1933': '丁卯', '1934': '壬申', '1935': '丁丑', '1936': '壬午', '1937': '戊子', '1938': '癸巳', '1939': '戊戌', '1940': '癸卯', '1941': '己酉', '1942': '甲寅', '1943': '己未', '1944': '甲子', '1945': '庚午', '1946': '乙亥', '1947': '庚辰', '1948': '乙酉', '1949': '辛卯', '1950': '丙申', '1951': '辛丑', '1952': '丙午', '1953': '壬子', '1954': '丁巳', '1955': '壬戌', '1956': '丁卯', '1957': '癸酉', '1958': '戊寅', '1959': '癸未', '1960': '戊子', '1961': '甲午', '1962': '己亥', '1963': '甲辰', '1964': '己酉', '1965': '乙卯', '1966': '庚申', '1967': '乙丑', '1968': '庚午', '1969': '丙子', '1970': '辛巳', '1971': '丙戌', '1972': '辛卯', '1973': '丁酉', '1974': '壬寅', '1975': '丁未', '1976': '壬子', '1977': '戊午', '1978': '癸亥', '1979': '戊辰', '1980': '癸酉', '1981': '己卯', '1982': '甲申', '1983': '己丑', '1984': '甲午', '1985': '庚子', '1986': '乙巳', '1987': '庚戌', '1988': '乙卯', '1989': '辛酉', '1990': '丙寅', '1991': '辛未', '1992': '丙子', '1993': '壬午', '1994': '丁亥', '1995': '壬辰', '1996': '丁酉', '1997': '癸卯', '1998': '戊申', '1999': '癸丑', '2000': '戊午', '2001': '甲子', '2002': '己巳', '2003': '甲戌', '2004': '己卯', '2005': '乙酉', '2006': '庚寅', '2007': '乙未', '2008': '庚子', '2009': '丙午', '2010': '辛亥', '2011': '丙辰', '2012': '辛酉', '2013': '丁卯', '2014': '壬申', '2015': '丁丑', '2016': '壬午', '2017': '戊子', '2018': '癸巳', '2019': '戊戌', '2020': '癸卯', '2021': '己酉', '2022': '甲寅', '2023': '己未', '2024': '甲子', '2025': '庚午', '2026': '乙亥', '2027': '庚辰', '2028': '乙酉', '2029': '辛卯', '2030': '丙申', '2031': '辛丑', '2032': '丙午', '2033': '壬子', '2034': '丁巳', '2035': '壬戌', '2036': '丁卯', '2037': '癸酉', '2038': '戊寅', '2039': '癸未', '2040': '戊子', '2041': '甲午', '2042': '己亥', '2043': '甲辰', '2044': '己酉', '2045': '乙卯', '2046': '庚申', '2047': '乙丑', '2048': '庚午', '2049': '丙子', '2050': '辛巳', '2051': '丙戌', '2052': '辛卯', '2053': '丁酉', '2054': '壬寅', '2055': '丁未', '2056': '壬子', '2057': '戊午', '2058': '癸亥', '2059': '戊辰', '2060': '癸酉', '2061': '己卯', '2062': '甲申', '2063': '己丑', '2064': '甲午', '2065': '庚子', '2066': '乙巳', '2067': '庚戌', '2068': '乙卯', '2069': '辛酉', '2070': '丙寅', '2071': '辛未', '2072': '丙子', '2073': '壬午', '2074': '丁亥', '2075': '壬辰', '2076': '丁酉', '2077': '癸卯', '2078': '戊申', '2079': '癸丑', '2080': '戊午', '2081': '甲子', '2082': '己巳', '2083': '甲戌', '2084': '己卯', '2085': '乙酉', '2086': '庚寅', '2087': '乙未', '2088': '庚子', '2089': '丙午', '2090': '辛亥', '2091': '丙辰', '2092': '辛酉', '2093': '丁卯', '2094': '壬申', '2095': '丁丑', '2096': '壬午', '2097': '戊子', '2098': '癸巳', '2099': '戊戌', '2100': '癸卯'}

  天数差的计算需要注意大小月,以及特殊的2月天数,闰年为29天,平年28天,故还需判断是否闰年,闰年判断实现如下:

def is_leap_year(year):if year % 4 == 0:if year % 100 == 0:if year % 400 == 0:return True  # 能被400整除的是闰年else:return False  # 能被100整除但不能被400整除的不是闰年else:return True  # 能被4整除但不能被100整除的是闰年else:return False  # 不能被4整除的不是闰

  大小月的判断通过一个长度为12的列表实现,表示对应月份前面有多少个大月即可:

BIG_MONTHS = [0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6]

  第1个元素表示1月份前有0个大月,第2、3月前面有1个大月,依次类推。
  日柱实现代码如下:

def __cal_day_ganzhi(self):# 计算日期的天干地支year, month, day = self.datetime.year, self.datetime.month, self.datetime.dayyuan_dan = YUNDAN_GANZHI[str(year)]days = BIG_MONTHS[month - 1] * 31 + 30 * (month - 1 - BIG_MONTHS[month - 1]) * 30 + dayif month > 2:days -= 1 if self.is_leap_year(year) else 2gz = list(GANZHI_ELEMENTS.keys())return gz[(gz.index(yuan_dan) + day) % 60

  5.时柱算法与实现

  时柱计算比较简单,古人将现在的24小时分为12个时辰,和地支数一致,各时辰和地支的关系是固定的,时辰的换算关系是,小时数加1整除以2的商对12取余,Python索引从0开始,再减1即可。
  时柱天干计算公式依赖于日柱天干,为天干数乘以2再加上时支(子丑寅卯辰巳午未申酉戌亥对应时支依次为-1,0,1,。。。,10)得到天干支数。
  时柱实现如下:

def __cal_hour_ganzhi(self):# 计算时间的天干地支hour = self.datetime.hourhour = (hour + 1) // 2 % 12dizhi = DIZHI[hour]ans = (TIANGAN.index(self.__cal_day_ganzhi()[0]) + 1) * 2 + DIZHI.index(dizhi) - 1return TIANGAN[ans % 10 - 1] + dizhi

五、程序实现

  设计calculate_five_elements类,zhdate为其基类,需要实现农历和公历两种类型时间的五行计算,类参数为农历的年月日,以及小时,基于zhdate基类实现到公历的转换:

class calculate_five_elements(ZhDate):# 在这里编写根据生辰计算五行的逻辑def __init__(self, lunar_year, lunar_month, lunar_day, lunar_hour, leap_month=False):super().__init__(lunar_year, lunar_month, lunar_day, leap_month)self.lunar_datetime = DATE_TIME(year=lunar_year, month=lunar_month, day=lunar_day, hour=lunar_hour)  # 农历时间self.datetime = super().to_datetime()self.datetime = DATE_TIME(year=self.datetime.year, month=self.datetime.month, day=self.datetime.day, hour=lunar_hour)  # 公历时间self.month_dates = self.__jieqi_date(datetime(self.datetime.year, self.datetime.month, self.datetime.day))

  设计静态函数,实现公历的五行转换,具体为调用zhdate基类转换方法转换公历得到农历,返回calculate_five_elements类,具体实现如下:

@staticmethoddef from_datetime(year, month, day, hour):cur_date = ZhDate.from_datetime(datetime(year, month, day))return calculate_five_elements(cur_date.lunar_year, cur_date.lunar_month, cur_date.lunar_day, hour)

  最后调用类方法five_elements,返回生辰八字和五行(时柱五行返回了两种结果,一是纳音五行,二是时柱五行只看地支的五行,不同流派计算有差异),方法实现如下:

def five_elements(self):year_gz = self.__cal_year_ganzhi()month_gz = self.__cal_month_ganzhi()day_gz = self.__cal_day_ganzhi()hour_gz = self.__cal_hour_ganzhi()gz = [year_gz, month_gz, day_gz, hour_gz]nayin_five = GANZHI_ELEMENTS[year_gz], GANZHI_ELEMENTS[month_gz], GANZHI_ELEMENTS[day_gz], [GANZHI_ELEMENTS[hour_gz], DIZHI_ELEMENTS[DIZHI.index(hour_gz[-1])]]return gz, nayin_five

  简单测试如下:

if __name__ == "__main__":# 公历日期date1 = calculate_five_elements.from_datetime(2023, 7, 18, 11)print(date1.five_elements())# 农历日期date2 = calculate_five_elements(2023, 6, 1, 11)print(date2.five_elements())

  输出结果如下:

  从结果中可以看出,公历2023年7月18日11时和农历2023年6月1日11时实际为同一天,分别用农历和公历算出的生辰八字和五行是一致的。
  程序运行系统配置及开发环境如下:

windows10专业版下的WSL2,Centos7.9发行版,python2.10.12

  完整代码下载请点击此处。

Python纳音五行计算相关推荐

  1. 五行顺口溜_纳音五行口诀

    纳音五行口诀: 子午银灯架壁钩, 辰戌烟满寺钟楼. 申寅汉地燥柴湿, 纳音五行此中求. 注释: 1 . 子午.辰戌.申寅:即分别以甲子.甲午,甲辰.甲戌,甲申.甲寅为开头 顺排的六十花甲中的六旬. 2 ...

  2. js 万历年五行纳音算法

    <script type="text/javascript"> /*write my adengou 2015.3.22 */ var _FiveElements ={ ...

  3. php编写六十甲子纳音表_六十甲子纳音表

    何为六十甲子纳音?十天干与十二地支按顺序两两相配, 从甲子到癸亥, 共六十个组合, 故称六十甲子. 每两组配一纳音五行.亦称六十花甲子. 六十甲子纳音表 甲子 乙丑 海中金 丙寅 丁卯 炉中火 戊辰 ...

  4. php编写六十甲子纳音表_史上最完整的六十甲子纳音表详细说明

    六十甲子是汉族人民最早和最大的发明,其历史已有上千年,其用途是纪年.纪月.纪日.纪时.在古时候,就是我们的时钟,以六十年为一个周期,纪月为五年一个周期,纪日为六十天一个周期,纪时为五天一个周期.接下来 ...

  5. php编写六十甲子纳音表_六十甲子顺序表

    六十甲子有时写作60甲子是最古老的用途,60甲子是纪年.纪月.纪日.纪时,60甲子纪年为60年一个周期,60甲子纪月为5年一个周期,60甲子纪日为60天一个周期,60甲子纪时为5天一个周期. ①六十甲 ...

  6. php编写六十甲子纳音表,六十花甲子纳音表

    什么是六十花甲子纳音,关于六十花甲子纳音查询表又有哪些呢?下面就让我们一起来了解下吧,希望可以帮到您! 六十花甲子纳音表 什么是六十花甲子纳音 六十花甲子中,把人分为金木水火土五种命,这五种命存在和发 ...

  7. php编写六十甲子纳音表_六十甲子纳音 六十花甲纳音表

    何为六十甲子纳音?十天干与十二地支按顺序两两相配, 从甲子到癸亥, 共六十个组合, 故称六十甲子. 每两组配一纳音五行.亦称六十花甲子. 六十甲子纳音表 甲子乙丑海中金 丙寅丁卯炉中火 戊辰己巳大林木 ...

  8. C语言 生辰八字+五行+纳音 查询

    干支是天干和地支的总称. 把干支顺序相配正好六十为一周,周而复始,循环记录,这就是俗称的"干支表". 甲.乙.丙.丁.戊.己.庚.辛.壬.癸 等十个符号叫天干; 子.丑.寅.卯.辰 ...

  9. 五行顺口溜_五行纳音口诀,五行相生相克歌诀

    六十甲子是汉族人民最早最大的发明创造,用来纪年.纪月.纪日.纪时.而六十甲子中也有关于五行的相关解说,那么你知道五行相生相克歌诀是什么吗?本期的五行相生相克带你去了解. 六十甲子五行纳音口诀 海沙箔锋 ...

最新文章

  1. caffe finetune predict and classify the lung nodule( 肺结节的分类)
  2. python staticmethodclassmethod
  3. python散点图点的大小-python散点图面积大小比例轴长度
  4. [云炬创业基础笔记] 第四章测试3
  5. vue 使用了浏览器的刷新之后报错_Laravel 7 + vue.js 学习笔记(一)
  6. JavaScript入门(part12)--内置对象
  7. 离线排序——LR模型
  8. [20170925]什么是FQDN(关于hostname).txt
  9. R语言基础期末大作业
  10. Mysql数据库恢复到指定时间点
  11. pcb地线应该不应该做成环路_电源PCB设计流程及要点全解析
  12. 帝国cms模板 php代码 效率,帝国cms模板开发常用技巧总结
  13. lav点搜网metro风格分享
  14. vite+vue3+TS项目引入antd-vue的问题记录
  15. js 大数字单位处理 千、万、千万、亿....
  16. 【论文解读 AAAI 2020 | Bi-GCN】Rumor Detection on Social Media with Bi-Directional GCN
  17. SecureCrt 的配色方案
  18. Linux上烧录CD
  19. c语言循环龙珠,《今天赛亚人也在拯救世界!》c语言黑板擦 ^第5章^ 最新更新:2020-01-09 03:52:51 晋江文学城手机版...
  20. sqlserver根据DATEDIFF()函数计算年龄、月龄、天数

热门文章

  1. 北京待售商品房数量信息将在网上全面公示
  2. java学习基础联系题 使用if··else if ···else循环语句设计公交车刷卡程序
  3. java-php-python-科大学生党员之家设计计算机毕业设计
  4. 蓝牙RSSI定位入门到精通(3)-指纹法实现
  5. VLOOKUP函数用法(1)将两个表按相同数据进行匹配
  6. 氨基/羧基/醛基/苯肼基/磺酸基/醛基化改性交联修饰聚苯乙烯微球的研究
  7. 手机上怎样压缩照片?这个办法很实用
  8. 关于《Python 从入门到实践》Django 创建学习主页 网站响应出现“Template-loader postmortem”的解决方法
  9. google浏览器打开自动启动桔梗网的问题
  10. 软件测试原则的6个基本原则