背景
TkDocs tutorial 里介绍了 Tkinter,其中有 A First (Real) Example 一文,这篇文章里有一个使用 Tkinter 生成图形化界面的简单例子。我想在那篇文章的基础上实战一下,于是想到可以写一个公元年份 ➡️ 干支纪年(其实严格来讲,一个公元年份并不能和一个干支纪年完全对应)的简易计算器。
正文
如何将公元年份转化为干支纪年
天干有如下 10 个
- 甲
- 乙
- 丙
- 丁
- 戊
- 己
- 庚
- 辛
- 壬
- 癸
地支有如下 12 个
- 子
- 丑
- 寅
- 卯
- 辰
- 巳
- 午
- 未
- 申
- 酉
- 戌
- 亥
计算对应的天干
公元 1984 年是甲子年。由于天干的数量是 10,所以可以这样计算天干 ⬇️
python
def calculate_tian_gan(specified_year):
tian_gan_candidates = "甲乙丙丁戊己庚辛壬癸"
candidates_cnt = len(tian_gan_candidates)
last_digit = specified_year % candidates_cnt
return tian_gan_candidates[(last_digit + 6) % candidates_cnt]
计算对应的地支
天干的数量( 10)和地支的数量( 12)都是( 60)的约数,所以对公元年份 y 和 y+60 而言(假设 y>0),它们对应的干支纪年是一样的。
公元 1984 年是甲子年,那么公元 184 年也是甲子年( 1984−60×30=184),那么公元 4 年也是甲子年( 184−60×3=4),所以可以这样计算地支 ⬇️
python
def calculate_di_zhi(specified_year):
di_zhi_candidates = "子丑寅卯辰巳午未申酉戌亥"
candidates_cnt = len(di_zhi_candidates)
remaider = specified_year % candidates_cnt
return di_zhi_candidates[(remaider + 8) % candidates_cnt]
完整的代码
A First (Real) Example 一文中有使用 Tkinter 生成图形化界面的简单例子。在它的基础上,可以写出以下 Python3 代码
python
from tkinter import *
from tkinter import ttk
def calculate():
try:
specified_year = year.get()
if (specified_year <= 0):
result.set("请输入大于0的公元年份!")
return
tian_gan = calculate_tian_gan(specified_year)
di_zhi = calculate_di_zhi(specified_year)
result.set(tian_gan + di_zhi)
except ValueError:
pass
def calculate_tian_gan(specified_year):
tian_gan_candidates = "甲乙丙丁戊己庚辛壬癸"
candidates_cnt = len(tian_gan_candidates)
last_digit = specified_year % candidates_cnt
return tian_gan_candidates[(last_digit + 6) % candidates_cnt]
def calculate_di_zhi(specified_year):
di_zhi_candidates = "子丑寅卯辰巳午未申酉戌亥"
candidates_cnt = len(di_zhi_candidates)
remaider = specified_year % candidates_cnt
return di_zhi_candidates[(remaider + 8) % candidates_cnt]
root = Tk()
root.title("公元年份对应干支纪年计算器")
mainframe = ttk.Frame(root, padding=(3, 3, 12, 12))
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
year = IntVar()
year_entry = ttk.Entry(mainframe, width=7, textvariable=year)
year_entry.grid(column=2, row=1, sticky=(W, E))
ttk.Button(mainframe, text="对应的干支纪年:", command=calculate).grid(column=1, row=2, sticky=W)
ttk.Label(mainframe, text="公元年份:").grid(column=1, row=1, sticky=W)
result = StringVar()
ttk.Label(mainframe, textvariable=result).grid(column=2, row=2, sticky=(W, E))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
mainframe.columnconfigure(2, weight=1)
for child in mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
year_entry.focus()
root.bind("<Return>", calculate)
root.mainloop()
运行
请将上一小节展示的完整代码保存为 ganzhi.py。使用如下命令可以运行 ganzhi.py
bash
python3 ganzhi.py
运行效果如下

我们输入一个正数,例如当前年份 2026,效果如下

再用其他年份验证一下(例如 1984 年)

运行结果符合预期