生辰八字的计算

我们常说的生辰八字,是用天干地支表示人出生的年、月、日、时,合起来是八个字。

十天干,甲乙丙丁午己庚辛壬癸。

十二地支,子丑寅卯辰巳午未申酉戌亥。

十天干和十二地支依次相配,如“甲子”、“乙丑”,两者按固定的顺序相互配合一共组成六十个基本单位:

甲子、乙丑、丙寅、丁卯、戊辰、已巳、庚午、辛未、壬申、癸酉、

甲戌、乙亥、丙子、丁丑、戊寅、已卯、庚辰、辛巳、壬午、癸未、

甲申、乙酉、丙戌、丁亥、戊子、已丑、庚寅、辛卯、壬辰、癸巳、

甲午、乙未、丙申、丁酉、戊戌、已亥、庚子、辛丑、壬寅、癸卯、

甲辰、乙巳、丙午、丁未、戊申、已酉、庚戌、辛亥、壬子、癸丑、

甲寅、乙卯、丙辰、丁巳、戊午、已未、庚申、辛酉、壬戌、癸亥。

快速知道自己的生辰八字。

正常万年历上都会显示到年月日的干支。比如说2021年9月21就是辛丑年丁酉月壬申日,需要自己计算的只剩下具体的时辰了。

关于时辰的计算,分为天干的计算以及地支的计算,都比较简单。首先时辰的地支有直接的对应关系。

0-11-33-55-77-99-1111-1313-1515-1717-1919-2121-2323-0
子时丑时寅时卯时辰时巳时午时未时申时酉时戌时亥时子时

其次要定位时辰的干支需要根据当日的干支来判断,也就是日上起时法,具体是做法如下。

甲己还加甲——逢日干是甲或己的日子,子时的时干从甲上起

乙庚丙作初——逢日干是乙或庚的日子,子时的时干从丙上起

丙辛从戊起——逢日干是丙或辛的日子,子时的时干从戊上起

丁壬庚子居——逢日干是丁或壬的日子,子时的时干从庚上起

戊癸何方发,壬子是真途

当换成表格描述如下

日干
子时起甲子丙子戊子庚子壬子

比如说今天是壬申日,日干支为壬,从上面的丁壬庚子居这句,那么可以得出今天的0点到1点为庚子时,接下来1点到3点是辛丑时,以此类推,壬寅,癸卯,甲辰,乙巳,丙午,丁未,戊申,己酉,庚戌,辛亥,到最后的23点又回到子时,不过此时已经是壬子了,正应了戊癸何方发,壬子是真途那句,因为当前壬申日接下来第二天是癸酉日,刚好以壬子起时。

以上,可以快速的得出自己的生辰八字。如果只是想了解下自己的八字,这就足够了。以上是时辰的推导过程,下面会讲一些年月日的推导规则,想了解的可以继续往下阅读。

干支纪年

前面说过十天干和十二地支依次相配,可以组成六十个基本单位。所以每六十年一个甲子轮回,而其中,每十年一个天干轮回,

可以挑一个最近的甲子年1984作为基准,用计算的年份-1984,然后对结果除以60取余数,从甲子往后推这个余数对应的干支即可。

当然更方便的是根据年份尾数直接推算天干,如下对应:

0123456789

年份÷12取余数,然后从子往后推余数次就是对应的地支。

例如,计算2021年的年干支,尾数为1,那么年干为辛,(2021-1984)÷12余数是1,子往后一个是丑,所以2021是辛丑年。

干支纪月

月份的地支也是固定的,每年的正月是寅月开始,二月是卯月,以此类推。

月份的干支计算,之前计算时辰的时候我们已经用到了日上起时法,此处我们同样要用到类似的年上起月法。

甲己之年丙作首,乙庚之岁戊为头。

丙辛岁首寻庚起,丁壬壬位顺行流。

若言戊癸何方求,甲寅之上好追求。

换成表格表述如下。

年干
正月起丙寅戊寅庚寅壬寅甲寅

2021年是辛丑年,那么正月是庚寅月,二月是辛卯月,以此类推,三月壬辰,四月癸巳,五月甲午,六月乙未,七月丙申,八月丁酉,九月戊戌,十月己亥,十一月庚子,十二月辛丑。来年壬寅年对应的正月刚好是壬寅月。

需要注意的是,这里说的月份皆是阴历。

干支纪日

正常情况下,日干支是最难算的,如果一个月固定三十天,那正好两月一个轮回,主要是考虑大小润月的问题,这里有一个公历计算的公式

已知日期计算干支纪日的公式为:

g = 4c + [c / 4] + 5y + [y / 4] + [3 * (m + 1) / 5] + d - 3

z = 8c + [c / 4] + 5y + [y / 4] + [3 * (m + 1) / 5] + d + 7 + i

其中 c 是世纪数减一,y 是年份后两位(若为1月2月则当前年份减1),m 是月份,d 是日数。1月和2月按上一年的13月和14月来算。奇数月i=0,偶数月i=6。g 除以10的余数是天干,z 除以12的余数是地支。 计算时带[ ]的数表示取整。

例如:查2021年9月21日的干支日。 将数值代入计算公式。 g =4*20 + [20 / 4] + 5*21 + [21 / 4] + [3 * (9 + 1) / 5] + 21 - 3 =219 除以10 余数为 9 ,天干的第9位是‘壬’。 z =8*20 + [20 / 4] + 5*21 + [21 / 4] + [3 * (9 + 1) / 5] + 21 + 7 + 0 =309 除以12 余数为 9 ,地支的第9位是‘申’,所以这一天是壬申日。

又如:查2021年1月1日的干支日。

世纪数c是20,y本来是21,因为1月所以减为20,m本来是1,因为是1月所以变为13,d是1,i是0.

将数值代入计算公式。 g =4*20 + [20 / 4] + 5*20 + [20 / 4] + [3 * (13 + 1) / 5] + 1- 3 =215除以10 余数为 6 ,天干的第6位是‘己’。 z =8*20 + [20 / 4] + 5*20 + [20 / 4] + [3 * (13 + 1) / 5] +1+ 7 + 0 =286 除以12 余数为 10 ,地支的第10位是‘酉’,所以这一天是己酉日。

规则讲完了,如果要用代码要怎么实现呢?

java实现

首先定义一个干支对象

    public static class GanZhi {
        /**
         * 天干序号
         */
        int tianGan;
        /**
         * 地支序号
         */
        int diZhi;

        public GanZhi() {
        }

        public GanZhi(int tianGan, int diZhi) {
            this.tianGan = tianGan;
            this.diZhi = diZhi;
        }
    }

再定义一些辅助的变量

// 第一个甲子年
private final static int FIRST_YEAR = -2697;
// 十天干
private final static String[] tianGanArray = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
// 十二地支
private final static String[] diZhiArray = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
// 年上起月,key为年天干序号,value为对应的月天干序号
private final static Map<Integer, Integer> yearMonthMap = new HashMap<>(4);
// 日上起时,key为日天干序号,value为对应的时天干序号
private final static Map<Integer, Integer> dayHourMap = new HashMap<>(4);


    static {
        /**
         * 年上起月法:
         * 甲己之年丙作首.
         * 乙庚之岁戊为头.
         * 丙辛之岁寻庚上.
         * 丁壬壬寅顺水顺.
         * 若问戊癸何处起.
         * 甲寅之上好追求
         */
        yearMonthMap.put(0, 2);
        yearMonthMap.put(1, 4);
        yearMonthMap.put(2, 6);
        yearMonthMap.put(3, 8);
        yearMonthMap.put(4, 0);
        yearMonthMap.put(5, 2);
        yearMonthMap.put(6, 4);
        yearMonthMap.put(7, 6);
        yearMonthMap.put(8, 8);
        yearMonthMap.put(9, 0);

        /**
         * 甲己还加甲
         * 乙庚丙作初
         * 丙辛从戊起
         * 丁壬庚子居
         * 戊癸何方发,壬子是真途
         */
        dayHourMap.put(0, 0);
        dayHourMap.put(1, 2);
        dayHourMap.put(2, 4);
        dayHourMap.put(3, 6);
        dayHourMap.put(4, 8);
        dayHourMap.put(5, 0);
        dayHourMap.put(6, 2);
        dayHourMap.put(7, 4);
        dayHourMap.put(8, 6);
        dayHourMap.put(9, 8);
    }

下面是相关信息

/**
 * 阴历日日期
 */
private Integer[] realBirth;
/**
 * 阳历日期
 */
private Integer[] yangbirths;

/**
 * 年干支
 */
private GanZhi yearGanZhi = null;
/**
 * 月干支
 */
private GanZhi monthGanZhi = null;
/**
 * 日干支
 */
private GanZhi dayGanZhi = null;
/**
 * 时干支
 */
private GanZhi hourGanZhi = null;

纪年

计算年份的干支方法,用年份减去目前已确定的第一个甲子年,也就是公元前求2697年求余数。year为正数表示公元xx年,为负数表示公元前xx年。由于不存在公元0年,假设-1年为甲子年,按照纯数字的推导,接下来应该是0是乙丑年,1是丙寅年。但是这个0是不存在的,1才应该是乙丑年。也就是说正数序列都要往前挪一位。所以year>0时,多减了1。当year为负数时,不需要多减1,但是需要取余数的绝对值。

public void evalYear(int year) throws Exception {
    if (year == 0) {
        throw new Exception("非法的年份");
    }
    int yeanGan = 0, yearZhi = 0;
    if (year > 0) {
        yeanGan = (year - FIRST_YEAR - 1) % 10;
        yearZhi = (year - FIRST_YEAR - 1) % 12;
    } else if (year < 0) {
        yeanGan = Math.abs((year - FIRST_YEAR) % 10);
        yearZhi = Math.abs((year - FIRST_YEAR)) % 12;
    }
    this.setYearGanZhi(new GanZhi(yeanGan, yearZhi));
}

纪月

年上起月,从yearMonthMap映射关系里,根据年天干获取到正月的月天干。正月地支初始化为寅,然后依次找到对应月份的干支。

public void evalMonth(int month) throws Exception {
    if (month < 1 || month > 12) {
        throw new Exception("非法的月份");
    }
    // 月份的起始干支(*寅)
    Integer monthGanInit = yearMonthMap.get(this.getYearGanZhi().getTianGan());
    Integer monthZhiInit = 2;
    for (int i = 1; i < month; i++) {
        monthGanInit = (monthGanInit + 1) % 10;
        monthZhiInit = (monthZhiInit + 1) % 12;
    }
    this.setMonthGanZhi(new GanZhi(monthGanInit, monthZhiInit));
}

纪日

代公式即可。

这个地方有一个疑惑点,就是计算2000年1月1日的这种日子,按照前面的说法,y 是年份后两位(若为1月2月则当前年份减1),这块的减1是对2000减1还是对余数0减一。翻了下日历,用余数减1的值匹配的上,不过感觉这个描述怪怪的。

public void evalDay(int day) throws Exception {
    int C = this.yangbirths[0] / 100;
    int y = this.yangbirths[1] > 2 ? this.yangbirths[0] % 100 : this.yangbirths[0] % 100 - 1;
    int M = this.yangbirths[1] > 2 ? this.yangbirths[1] : this.yangbirths[1] + 12;
    int d = this.yangbirths[2];
    int i = this.yangbirths[1] % 2 == 0 ? 6 : 0;

    // 月份的起始干支(*寅)
    Integer monthGanInit = (4 * C + (C / 4) + 5 * y + (y / 4) + (3 * (M + 1) / 5) + d - 3 - 1) % 10;
    Integer monthZhiInit = (8 * C + (C / 4) + 5 * y + (y / 4) + (3 * (M + 1) / 5) + d + 7 + i - 1) % 12;

    this.setDayGanZhi(new GanZhi(monthGanInit, monthZhiInit));
}

计时

日上起时,两个小时为一个时辰,所以每循环一次,i要加2

public void evalHour(int hour) throws Exception {
    if (hour < 0 || hour > 24) {
        throw new Exception("非法的小时");
    }
    // 月份的起始干支(*寅)
    Integer hourGanInit = dayHourMap.get(this.getDayGanZhi().getTianGan());
    Integer hourZhiInit = 0;
    for (int i = 1; i <= hour; i = i + 2) {
        hourGanInit = (hourGanInit + 1) % 10;
        hourZhiInit = (hourZhiInit + 1) % 12;
    }
    this.setHourGanZhi(new GanZhi(hourGanInit, hourZhiInit));
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值