Javascript实现生辰八字五行查询

前段时间宝宝出生了,兴奋之余,一直忙着给宝宝选名字,想起网上各式各样的五行查询,出于好奇研究了下算法,于是自己也试着写了个小程序。先上张截图:

“五行分析”

当然,首先就要先理解最基本的,什么是天干地支,什么是生辰八字,什么是五行。

1. 什么是天干地支

天干地支,简称为干支,源自远古时代对天象的观测。”甲、乙、丙、丁、戊、己、庚、辛、壬、癸”称为十天干,”子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥”称为十二地支。天干地支组成形成了古代纪年历法。十干和十二支依次相配,组成六十个基本单位,两者按固定的顺序相互配合,组成了干支纪法

2. 什么是生辰八字

生辰八字,简称八字,是指一个人出生时的干支历日期;年月日时共四柱干支,每柱两字,合共八个字,故称。生辰八字在汉族民俗信仰中占有重要地位,古代汉族星相家据此推算人的命运的好坏。在历书中,年的干支与日的干支基本都有,而月与时的天干可以依据年、日的干支按口诀推算得出。
上面说的年月日时干支,意思是把日期分成四部分:年、月、日、时。而每个日期又有天干和地支两部分,因此合起来就是:年干、年支、月干、月支、天干、天支、时干、时支。
众所周知,一个时辰是两个小时,具体的对应关系如下:

子时 丑时 寅时 卯时 辰时 己时
23:00-00:59 01:00-02:59 03:00-04:59 05:00-06:59 07:00-08:59 09:00-10:59
午时 未时 申时 酉时 戊时 亥时
11:00-12:59 13:00-14:59 15:00-16:59 17:00-18:59 19:00-20:59 21:00-22:59

3. 什么是五行

五行是中国自古以来道学的一种系统观,广泛地用于中医学、堪舆、命理、相术和占卜等方面。五行的意义包涵借着阴阳演变过程的五种基本动态:水(代表润下)、火(代表炎上)、金(代表收敛)、木(代表伸展)、土(代表中和)。中国古代哲学家用五行理论来说明世界万物的形成及其相互关系。它强调整体概念,旨在描述事物的运动形式以及转化关系。

4. 怎么知道哪个时辰的八字都是什么

首先知道天干、地支的五行含义:

1 2 3 4 5 6 7 8 9 10 11 12

具体的八字推算,老祖宗已经帮我们总结好了,问问度娘可以发现有很多种方法,我这里采用比较简单也易实现的一种:

年干支推算:
1.年干公式:年干=年份个位数- 3 (适用于任何西元年,个位数小于3,借10)
2.年支公式:年支=(年份+7)÷12余数(整除余0,即余12=丑)

通过以上公式,可以得出年干、年支与自然数的对应关系。
天干地支纪年法首先是天干在前,地支在后,比如今年2016就为——丙申年。

月干支推算:
月的地支是固定不变的:正月是寅,二月是卯,三月是子,依次类推…..也就是用年支的推算方式,年支和月支应该正好一致。
月干公式:月干=年干x2+月支 (和超过10,直接取个位数)

例:已知2015年为乙未年,求2015年申月天干?
解:2015年乙未年,天干为乙,乙=2,申=7

日干推算:日干推算比较复杂,我这里使用高氏日柱公式来进行推算。公式如下(具体含义可参考高氏日柱公式):

r=s/46+5(s/4*3+u)+m+d+x

日支推算:我这里采用的是用六十甲子表,直接查询日干结果在甲子表中对应的值。

时干推算:
①时支公式:时支=小时÷2-1(小时为偶数),时支=(小时+1)÷2-1(小时为奇数)
②时干公式:时干=日干×2+时支 (晨子=-1,夜子=11)

在这里吐槽一下网上流传很广的那些帖子,我找的六十甲子基本都是把自己的“己”给错写成了已经的“已”,导致有些日期查询异常。

到这里,知道了八字的计算方式和与自然数的对应关系,因此,可以用数组来描述这些关系,因为月干是需要与年份有关的,因此可以定义一个函数来获取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//天干序数:1(甲),2(乙),……
var __TianGan = ['', '甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'],
//地支序数:1(寅),2(卯),……
__NianZhi = ['', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥', '子', '丑'],
//月的地支序数:寅月为正月,……
__YueZhi = ['', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥', '子', '丑'],
__WuXing = {
'甲': '木',
'乙': '木',
'丙': '火',
'丁': '火',
'戊': '土',
'己': '土',
'庚': '金',
'辛': '金',
'壬': '水',
'癸': '水',
'寅': '木',
'卯': '木',
'辰': '土',
'巳': '火',
'午': '火',
'未': '土',
'申': '金',
'酉': '金',
'戌': '土',
'亥': '水',
'子': '水',
'丑': '土'
},
__JiaZi = [undefined,
'甲子', '乙丑', '丙寅', '丁卯', '戊辰', '已巳', '庚午', '辛未', '壬申', '癸酉', '甲戌', '乙亥',
'丙子', '丁丑', '戊寅', '已卯', '庚辰', '辛巳', '壬午', '癸未', '甲申', '乙酉', '丙戌', '丁亥',
'戊子', '己丑', '庚寅', '辛卯', '壬辰', '癸巳', '甲午', '乙未', '丙申', '丁酉', '戊戌', '已亥',
'庚子', '辛丑', '壬寅', '癸卯', '甲辰', '乙巳', '丙午', '丁未', '戊申', '已酉', '庚戌', '辛亥',
'壬子', '癸丑', '甲寅', '乙卯', '丙辰', '丁巳', '戊午', '已未', '庚申', '辛酉', '壬戌', '癸亥'
],
//时干支
__ShiGanZhi = {
'-1': '子',
'0': '丑',
'1': '寅',
'2': '卯',
'3': '辰',
'4': '巳',
'5': '午',
'6': '未',
'7': '申',
'8': '酉',
'9': '戌',
'10': '亥',
'11': '子'
};
/**
* 获取年干。公式:年干=年份个位数-3。适用于任何西元年,个位数小于3时,借10
* @param {Object} year
*/
function getNianGanIndex(year) {
//年干=年份个位数-3,个位数小于2,借10
var index = Number(year.toString().slice(-1, year.length));
index <= 3 && (index += 10);
index -= 3;
return index;
}
/**
* 获取年支。公式:年支=(年份+7)/12取余数。整除余0即12,为丑。
* @param {Object} year
*/
function getNianZhiIndex(year) {
return (Number(year) + 7) % 12 || 12;
}
/**
* 获取月干。公式:月干=年干*2+月支
* @param {Object} nianGanIndex
* @param {Object} lMonth
*/
function getYueGanIndex(nianGanIndex, lMonth) {
var index = Number(nianGanIndex) * 2 + Number(lMonth);
index %= 10;
return index;
}
/**
* 获取月支。公式:月支=农历月份
* @param {Object} lMonth
*/
function getYueZhiIndex(lMonth) {
return Number(lMonth);
}
/**
* 获取时支。公式:时支=小时/2 - 1(小时为偶数时),时支=(小时+1)/2 - 1(小时为奇数时)
* @param {Object} hour
*/
function getShiZhiIndex(hour) {
hour = Number(hour);
if (hour % 2 === 0) {
return hour / 2 - 1;
} else {
return (hour + 1) / 2 - 1;
}
}
/**
* 获取时干。公式:时干=日干*2 + 时支
* @param {Object} riGanIndex
* @param {Object} shiZhiIndex
*/
function getShiGanIndex(riGanIndex, shiZhiIndex) {
var index = (riGanIndex * 2 + shiZhiIndex) % 10;
index === 0 && (index = 10);
return index;
}

另外就是利用高氏日柱公式计算日干、日支方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 判断是否闰年
* @param {Object} year
*/
function isRunnian(year) {
year = Number(year);
if (year % 100 === 0) {
return year % 400 === 0;
} else {
return year % 4 === 0;
}
}
/**
* 获取月份基数
* | 月份 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
* | 月基数 | 0 | 31 | -1 | 30 | 0 | 31 | 1 | 32 | 3 | 33 | 4 | 34 |
* @param {Object} month
*/
function getMonthBase(month) {
month = Number(month);
var base = [undefined, 0, 31, -1, 30, 0, 31, 1, 32, 3, 33, 4, 34];
return base[month];
}
/**
* 获取指定年份所属的世纪
* @param {Object} year
*/
function getCenturyByYear(year) {
year = Number(year);
if (year % 100 === 0) {
return year / 100;
}
return parseInt(year / 100) + 1;
}
/**
* 根据世纪,计算该世纪常数。公式:X = 44*(C-17) + (C-17)/4 + 3。C:世纪,X:世纪常数
* @param {Object} century
*/
function getCenturyConst(century) {
century = Number(century);
return (44 * (century - 17) + parseInt((century - 17) / 4) + 3) % 60;
}
/**
* 根据高氏日柱公式,获取指定日期的天干地支。
* 公式:r = s/4*6 + 5*(s/4*3+u)+m+d+x。
* r:日柱的母数,r除以60取余,即时日柱的干支序列数。
* s:公元年数后两位减1,s/4取整数部分。
* u:s除以4的余数
* m:月基数
* d:日期数
* x:世纪常数
* @param {Object} year
* @param {Object} month
* @param {Object} date
*/
function getRiGan(year, month, date) {
year = Number(year);
var s = year % 100 - 1,
u = s % 4,
m = getMonthBase(month),
d = date,
x = getCenturyConst(getCenturyByYear(year));
// console.log('s:%s,u:%s,m:%s,d:%s,x:%s', s, u, m, d, x);
var r = parseInt(s / 4) * 6 + 5 * (parseInt(s / 4) * 3 + u) + m + d + x;
if (isRunnian(year) && month > 2) {
r += 1;
}
r %= 60;
r === 0 && (r = 60);
return r;
}

现在来想一下程序的结构:我希望的是和那些网站一样,选择出生年月日时,就可以给出结果。因此,可以定义成一个工具类,输入是日期对象,输出是八字和五行的分析结果。

另外,上面的公式只适用于公历,我希望可以用农历和公历两种方法进行推算。这里用到了一个插件calendar.js,可以进行公历农历的转换。

完整Demo点击下面链接(因为关注点没在日期校验上,所以对于日期并没有增加校验,如下拉列表每月的天数):

时辰八字五行分析