干支纪日介绍
干支纪日是中国传统历法中按顺序用天干地支相配来记录日序的方法,干支纪日法以天干和地支相配,组成六十个基本单位,依次循环纪日。天干有十个,即甲、乙、丙、丁、戊、己、庚、辛、壬、癸;地支有十二个,即子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥。将天干与地支按固定顺序两两组合,从 “甲子” 开始,到 “癸亥” 结束,共六十组,称为 “六十甲子”,一个周期结束后再从头循环。
五虎遁
五虎遁也叫 “年上起月法”,是根据年干来确定每个月的月干,因为一年有十二个月,地支对应固定不变(正月为寅、二月为卯、三月为辰,以此类推,直到十二月为丑),而月干则需依据年干通过五虎遁口诀来推算,就像老虎在山林中遁行一样有其特定规律,所以被称为五虎遁。
口诀内容
甲己之年丙作首,
乙庚之岁戊为头,
丙辛必定寻庚起,
丁壬壬位顺行流,
若问戊癸何方发,
甲寅之上好追求。
五鼠遁
五鼠遁,又称 “日上起时法”,是根据日的天干来确定当天各个时辰的时干。一天分为十二个时辰,每个时辰对应一个地支(23 - 1 点为子时、1 - 3 点为丑时、3 - 5 点为寅时,依此类推),而时干需要依据日干通过五鼠遁口诀来推算。
口诀内容
甲己还加甲,
乙庚丙作初,
丙辛从戊起,
丁壬庚子居,
戊癸何方发,
壬子是真途。
明确了上面的内容后,我们还是用代码实现将公历转换成干支纪日法
代码
package main
import (
"fmt"
"time"
)
// 天干数组
var heavenlyStems = []string{"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"}
// 地支数组
var earthlyBranches = []string{"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"}
// 五虎遁,用于根据年干确定月干
var fiveTigerEscape = [][]int{
{2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, // 甲己年
{4, 5, 6, 7, 8, 9, 0, 1, 2, 3}, // 乙庚年
{6, 7, 8, 9, 0, 1, 2, 3, 4, 5}, // 丙辛年
{8, 9, 0, 1, 2, 3, 4, 5, 6, 7}, // 丁壬年
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, // 戊癸年
}
// 五鼠遁,用于根据日干确定时干
var fiveRatEscape = [][]int{
{4, 5, 6, 7, 8, 9, 0, 1, 2, 3}, // 甲己日
{6, 7, 8, 9, 0, 1, 2, 3, 4, 5}, // 乙庚日
{8, 9, 0, 1, 2, 3, 4, 5, 6, 7}, // 丙辛日
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, // 丁壬日
{2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, // 戊癸日
}
// 公历年份转干支纪年
func yearToGanzhi(year int) string {
// 公元 4 年是甲子年
offset := year - 4
ganIndex := offset % 10
zhiIndex := offset % 12
return heavenlyStems[ganIndex] + earthlyBranches[zhiIndex]
}
// 公历月份转干支纪月
func monthToGanzhi(year, month int) string {
// 年干对应的五虎遁口诀
yearGanIndex := (year - 4) % 10
startGanIndex := fiveTigerEscape[yearGanIndex/5][yearGanIndex%5]
monthZhiIndex := (month + 1) % 12
monthGanIndex := (startGanIndex + month - 1) % 10
return heavenlyStems[monthGanIndex] + earthlyBranches[monthZhiIndex]
}
// 公历日期转干支纪日
func dayToGanzhi(year, month, day int) string {
// 1900 年 1 月 31 日是甲子日(这里为了更准确采用1949年10月1日为甲子日)
startDate := time.Date(1949, 10, 1, 0, 0, 0, 0, time.UTC)
currentDate := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
days := int(currentDate.Sub(startDate).Hours() / 24)
ganIndex := days % 10
zhiIndex := days % 12
return heavenlyStems[ganIndex] + earthlyBranches[zhiIndex]
}
// 公历小时转干支纪时
func hourToGanzhi(dayGan string, hour int) string {
// 日干对应的五鼠遁口诀
dayGanIndex := 0
for i, v := range heavenlyStems {
if v == dayGan {
dayGanIndex = i
break
}
}
startGanIndex := fiveRatEscape[dayGanIndex/5][dayGanIndex%5]
hourZhiIndex := (hour + 1) / 2 % 12
hourGanIndex := (startGanIndex + (hour+1)/2 - 1) % 10
return heavenlyStems[hourGanIndex] + earthlyBranches[hourZhiIndex]
}
func main() {
// 获取当前时间
now := time.Now()
year := now.Year()
month := int(now.Month())
day := now.Day()
hour := now.Hour()
// 计算干支
ganzhiYear := yearToGanzhi(year)
ganzhiMonth := monthToGanzhi(year, month)
ganzhiDay := dayToGanzhi(year, month, day)
dayGan := string(ganzhiDay[0])
ganzhiHour := hourToGanzhi(dayGan, hour)
fmt.Printf("公历 %d 年 %d 月 %d 日 %d 时,对应的天干地支表示为:%s 年 %s 月 %s 日 %s 时\n",
year, month, day, hour, ganzhiYear, ganzhiMonth, ganzhiDay, ganzhiHour)
}