一、引言
在日常工作中,批量计算人员年龄是一项常见但繁琐的任务,传统的手工处理方式不仅效率低下,还容易因人为操作导致错误。为此,我们开发了基于pyqt框架的批量年龄(周岁)计算工具,该工具能够从18位身份证号中自动提取出生日期(第7-14位为yyyymmdd格式),并结合用户指定的目标日期,高效、精准地计算出周岁年龄。同时支持将结果直接复制导出,便于后续数据分析与系统集成。
二、gui界面设计
使用pyqt5进行界面的搭建,界面如下:


初始界面搭建采用极简风格。当批量输入(也可直接从excel中复制粘贴)合法的身份证号码后,若其合法,点击“计算”后会在右侧给出对应年龄(周岁)结果;否则,会告知用户输入身份证号码存在不合法项并提示重新输入。
需要注意的是:该计算工具会结合用户指定的目标日期,高效、精准地计算出周岁年龄。如上图红框所示:当两者均为2000年出生,得到的年龄相差为1,原因在于前者是4月份出生(到2025年的10月7日满周岁),后者是11月份出生(到2025年的10月7日未满周岁)。
1.相关提示



在未输入身份证和未选择指定日期,进行“计算”操作后,均会给出提示;当用户输入的身份证存在长度错误或特殊字符时,提示“输入身份证有误,请重新输入”。
2.效果演示

3.界面设计.py
通过pyuic5产生的gui界面代码jiemian.py如下:
# -*- coding: utf-8 -*-
# form implementation generated from reading ui file 'jiemian.ui'
#
# created by: pyqt5 ui code generator 5.15.11
#
# warning: any manual changes made to this file will be lost when pyuic5 is
# run again. do not edit this file unless you know what you are doing.
from pyqt5 import qtcore, qtgui, qtwidgets
class ui_form(object):
def setupui(self, form):
form.setobjectname("form")
form.setenabled(true)
form.resize(360, 450)
form.setminimumsize(qtcore.qsize(360, 450))
form.setmaximumsize(qtcore.qsize(360, 450))
icon = qtgui.qicon()
icon.addpixmap(qtgui.qpixmap(":/image1.png"), qtgui.qicon.normal, qtgui.qicon.off)
form.setwindowicon(icon)
self.label_5 = qtwidgets.qlabel(form)
self.label_5.setgeometry(qtcore.qrect(210, 40, 141, 31))
font = qtgui.qfont()
font.setfamily("adobe arabic")
font.setpointsize(16)
self.label_5.setfont(font)
self.label_5.setobjectname("label_5")
self.label_8 = qtwidgets.qlabel(form)
self.label_8.setgeometry(qtcore.qrect(130, 10, 251, 31))
font = qtgui.qfont()
font.setfamily("adobe arabic")
font.setpointsize(18)
font.setbold(false)
font.setweight(50)
self.label_8.setfont(font)
self.label_8.setobjectname("label_8")
self.label_10 = qtwidgets.qlabel(form)
self.label_10.setgeometry(qtcore.qrect(290, 30, 71, 51))
self.label_10.settext("")
self.label_10.setpixmap(qtgui.qpixmap(":/image1.png"))
self.label_10.setobjectname("label_10")
self.textedit = qtwidgets.qtextedit(form)
self.textedit.setgeometry(qtcore.qrect(30, 110, 141, 201))
self.textedit.setobjectname("textedit")
self.textedit_2 = qtwidgets.qtextedit(form)
self.textedit_2.setgeometry(qtcore.qrect(200, 110, 141, 201))
self.textedit_2.setobjectname("textedit_2")
self.label = qtwidgets.qlabel(form)
self.label.setgeometry(qtcore.qrect(30, 85, 121, 21))
self.label.setobjectname("label")
self.label_2 = qtwidgets.qlabel(form)
self.label_2.setgeometry(qtcore.qrect(200, 90, 54, 12))
self.label_2.setobjectname("label_2")
self.pushbutton = qtwidgets.qpushbutton(form)
self.pushbutton.setgeometry(qtcore.qrect(30, 410, 311, 23))
self.pushbutton.setobjectname("pushbutton")
self.combobox = qtwidgets.qcombobox(form)
self.combobox.setgeometry(qtcore.qrect(40, 360, 67, 22))
self.combobox.setobjectname("combobox")
self.combobox_2 = qtwidgets.qcombobox(form)
self.combobox_2.setgeometry(qtcore.qrect(150, 360, 67, 22))
self.combobox_2.setobjectname("combobox_2")
self.combobox_3 = qtwidgets.qcombobox(form)
self.combobox_3.setgeometry(qtcore.qrect(260, 360, 67, 22))
self.combobox_3.setobjectname("combobox_3")
self.label_3 = qtwidgets.qlabel(form)
self.label_3.setgeometry(qtcore.qrect(110, 360, 16, 21))
self.label_3.setobjectname("label_3")
self.label_4 = qtwidgets.qlabel(form)
self.label_4.setgeometry(qtcore.qrect(220, 360, 21, 21))
self.label_4.setobjectname("label_4")
self.label_6 = qtwidgets.qlabel(form)
self.label_6.setgeometry(qtcore.qrect(330, 360, 21, 21))
self.label_6.setobjectname("label_6")
self.label_7 = qtwidgets.qlabel(form)
self.label_7.setgeometry(qtcore.qrect(30, 330, 121, 31))
self.label_7.setobjectname("label_7")
self.retranslateui(form)
qtcore.qmetaobject.connectslotsbyname(form)
def retranslateui(self, form):
_translate = qtcore.qcoreapplication.translate
form.setwindowtitle(_translate("form", "age_cal"))
self.label_5.settext(_translate("form", "designed by"))
self.label_8.settext(_translate("form", "年龄计算"))
self.label.settext(_translate("form", "请输入身份证号码:"))
self.label_2.settext(_translate("form", "年龄如下:"))
self.pushbutton.settext(_translate("form", "计算"))
self.label_3.settext(_translate("form", "年"))
self.label_4.settext(_translate("form", "月"))
self.label_6.settext(_translate("form", "日"))
self.label_7.settext(_translate("form", "请选择指定日期:"))
import ziyuan_rc
三、主要程序详解
1.导入相关模块
import sys, time from jiemian import * from pyqt5.qtwidgets import qapplication, qwidget # 保持窗口大小和qtdesigner中的一致 from pyqt5 import qtcore qtcore.qcoreapplication.setattribute(qtcore.qt.aa_enablehighdpiscaling)
导入前端页面设计文件:jiemian.py;不懂为啥需要导入qtcore的,请看一键曝光:python+pyqt实现的文件目录。
2.初始化设置
def __init__(self):
super(qwidget, self).__init__()
self.setupui(self)
self.pushbutton.clicked.connect(self.jisuan)
self.combobox.currentindexchanged.connect(self.day_show) # 年份选项发生改变
self.combobox_2.currentindexchanged.connect(self.day_show) # 月份选项发生改变
self.combobox.additem('请选择')
self.combobox_2.additem('请选择')
# 针对“年”
self.cur_nian = time.strftime("%y", time.localtime())
# 使用列表推导式增添选项
self.combobox.additems([str(int(self.cur_nian) + i) for i in range(-5, 6)]) # 年
self.combobox_2.additems([str(i) for i in range(1, 13)]) # 月pushbutton绑定于jisuan;当用户改变年度/月份时,对应的“日”也需要紧随变化,故将其绑定于day_show;同时在初始化时将年份combobox和月份combobox_2添加首选项“请选择”,日combobox暂时不做处理;接着通过time.strftime获取当前年份并存储于cur_nian中;以当前年份为时间中点,使用列表推导式往前往后各推5年添加至combobox中;最后再通过列表推导式添加12个月份。
3.“日”选项的设置
def day_show(self):
"""主要对日进行设置,因为其不仅与月份有关,还与年份有关(闰年的2月)"""
self.combobox_3.clear()
self.combobox_3.additem('请选择')
yue_text = self.combobox_2.currenttext() # 判断用户选择的是哪个月
if yue_text in ['1', '3', '5', '7', '8', '10', '12']: # 31天的月份
self.combobox_3.additems([str(i) for i in range(1, 32)])
elif yue_text in ['4', '6', '9', '11']: # 30天的月份
self.combobox_3.additems(str(i) for i in range(1, 31))
elif yue_text == '2': # 针对2月要特殊处理
if self.combobox.currentindex() != 0: # 除去年份为“请选择”的特殊情况
if year_judge(self.combobox.currenttext()): # 为闰年,2月为29天
self.combobox_3.additems([str(i) for i in range(1, 30)])
else: # 不为闰年,2月为28天
self.combobox_3.additems([str(i) for i in range(1, 29)])
else: # 表示月份的“请选择”选项
pass与其他combobox一样,combobox_3“日下拉框”也需要clear()和添加首选项“请选择”;combobox_3其不仅取决于“年下拉框”combobox是否为闰年,而且还取决于“月下拉框”combobox_2的选择(有31天的月份,也有30天的月份);所以先判断combobox_2的text是否在31天和30天的月份中,如果存在,直接使用列表推导式additems即可;否则如果为2月,还需通过自定义函数year_judge判断当前年份是否为闰年;如果为闰年,则列表推导式产生29天,否则产生28天;此时,combobox_3未讨论情况只剩下“请选择”选项,pass即可。
4.年龄(周岁)的计算
def jisuan(self):
shuru = self.textedit.toplaintext() # 读取的默认类型为str
if shuru != "": # 用户输入不为空时
if (self.combobox.currentindex()!=0) and(self.combobox_2.currentindex()!=0) and (self.combobox_3.currentindex()!=0): # 用户做出年月日的选择
shuru_nian = self.combobox.currenttext()
shuru_yue = self.combobox_2.currenttext()
shuru_ri = self.combobox_3.currenttext()
zhiding_riqi = riqi_return(shuru_nian,shuru_yue,shuru_ri) # 合并为yyyymmdd的形式
shuru_list = shuru.split() # 以换行符分割
riqi = [i[6:14] for i in shuru_list] # 截取所有身份证的8位日期
jieguo =[] # 年龄差存放
for i in riqi:
if (len(i) == 8) and i.isdigit(): # 长度为8且均为数字
jieguo.append(niancha_cal(zhiding_riqi, i))
else:
qtwidgets.qmessagebox.critical(self, "提示", "输入身份证有误,请重新输入!")
break
self.textedit_2.clear() # 清除上次结果
for item in jieguo:
self.textedit_2.append(str(item))
else:
qtwidgets.qmessagebox.critical(self, "提示", "请选择指定日期!")
else:
qtwidgets.qmessagebox.critical(self, "提示", "请输入身份证号!")当用户输入不为空时,判断用户是否进行了“年月日”的选择(依据item的索引);若用户已经进行选择,则读取年月日并存储,通过调用自定义函数riqi_return从而返回yyyymmdd的日期规范格式;再通过对用户输入的所有身份证进行切片操作,获取8位日期,并与上述yyyymmdd通过自定义函数niancha_cal进行比较和计算,将得到的结果添加至jieguo中;最后通过循环显示到textedit_2中。
5.自定义函数
def year_judge(year):
"""判断用户输入是否为闰年"""
if (int(year)%4==0) and (int(year)%100!=0):
return true
elif int(year)%400==0:
return true
else:
return false闰年的标志:能被4整除的同时,但不能被100整除;或者是能被400直接整除。
def riqi_return(nian, yue, ri):
"""将年月日三数字转换合并为yyyymmdd形式"""
if (int(yue)<10): # 单月形式
if (int(ri)<10): # 单日
return nian+'0'+yue+'0'+ri # 补零操作
else:
return nian+'0'+yue+ri
else:
if (int(ri) < 10):
return nian+yue+'0'+ri
else:
return nian+yue+ri通过分支结构,在单数字前进行补零,最后将字符串拼接即可得到yyyymmdd形式。
def niancha_cal(date1, date2):
# 默认date1先于date2
if int(date1)<int(date2): # 交换两者顺序
temp = date1
date1 = date2
date2 = temp
if int(date1[4:6]) < int(date2[4:6]): # 判断月的大小关系
return int(date1[0:4])-int(date2[0:4])-1 # 不满周岁得减一
elif int(date1[4:6]) > int(date2[4:6]):
return int(date1[0:4])-int(date2[0:4])
else:
if int(date1[6:8]) < int(date2[6:8]): # 进一步判断“日”的大小关系
return int(date1[0:4]) - int(date2[0:4]) - 1 # 不满周岁得减一
else:
return int(date1[0:4]) - int(date2[0:4])默认date1先于date2,否则进行交换;接下来截取月份和日进行比较,最终截取年份相减,根据是否满周岁判断是否多减一。
四、总程序代码
import sys, time
from jiemian import *
from pyqt5.qtwidgets import qapplication, qwidget
# 保持窗口大小和qtdesigner中的一致
from pyqt5 import qtcore
qtcore.qcoreapplication.setattribute(qtcore.qt.aa_enablehighdpiscaling)
class window(qwidget, ui_form):
def __init__(self):
super(qwidget, self).__init__()
self.setupui(self)
self.pushbutton.clicked.connect(self.jisuan)
self.combobox.currentindexchanged.connect(self.day_show) # 年份选项发生改变
self.combobox_2.currentindexchanged.connect(self.day_show) # 月份选项发生改变
self.combobox.additem('请选择')
self.combobox_2.additem('请选择')
# 针对“年”
self.cur_nian = time.strftime("%y", time.localtime())
# 使用列表推导式增添选项
self.combobox.additems([str(int(self.cur_nian) + i) for i in range(-5, 6)]) # 年
self.combobox_2.additems([str(i) for i in range(1, 13)]) # 月
def day_show(self):
self.combobox_3.clear()
self.combobox_3.additem('请选择')
yue_text = self.combobox_2.currenttext() # 判断用户选择的是哪个月
if yue_text in ['1', '3', '5', '7', '8', '10', '12']: # 31天的月份
self.combobox_3.additems([str(i) for i in range(1, 32)])
elif yue_text in ['4', '6', '9', '11']: # 30天的月份
self.combobox_3.additems(str(i) for i in range(1, 31))
elif yue_text == '2': # 针对2月要特殊处理
if self.combobox.currentindex() != 0: # 除去年份为“请选择”的特殊情况
if year_judge(self.combobox.currenttext()): # 为闰年,2月为29天
self.combobox_3.additems([str(i) for i in range(1, 30)])
else: # 不为闰年,2月为28天
self.combobox_3.additems([str(i) for i in range(1, 29)])
else: # 表示月份的“请选择”选项
pass
def jisuan(self):
shuru = self.textedit.toplaintext() # 读取的默认类型为str
if shuru != "": # 用户输入不为空时
if (self.combobox.currentindex()!=0) and(self.combobox_2.currentindex()!=0) and (self.combobox_3.currentindex()!=0): # 用户做出年月日的选择
shuru_nian = self.combobox.currenttext()
shuru_yue = self.combobox_2.currenttext()
shuru_ri = self.combobox_3.currenttext()
zhiding_riqi = riqi_return(shuru_nian,shuru_yue,shuru_ri) # 合并为yyyymmdd的形式
shuru_list = shuru.split() # 以换行符分割
riqi = [i[6:14] for i in shuru_list] # 截取所有身份证的8位日期
jieguo =[] # 年龄差存放
for i in riqi:
if (len(i) == 8) and i.isdigit(): # 长度为8且均为数字
jieguo.append(niancha_cal(zhiding_riqi, i))
else:
qtwidgets.qmessagebox.critical(self, "提示", "输入身份证有误,请重新输入!")
break
self.textedit_2.clear() # 清除上次结果
for item in jieguo:
self.textedit_2.append(str(item))
else:
qtwidgets.qmessagebox.critical(self, "提示", "请选择指定日期!")
else:
qtwidgets.qmessagebox.critical(self, "提示", "请输入身份证号!")
def year_judge(year):
"""判断用户输入是否为闰年"""
if (int(year)%4==0) and (int(year)%100!=0):
return true
elif int(year)%400==0:
return true
else:
return false
def riqi_return(nian, yue, ri):
"""将年月日三数字转换合并为yyyymmdd形式"""
if (int(yue)<10): # 单月形式
if (int(ri)<10): # 单日
return nian+'0'+yue+'0'+ri # 补零操作
else:
return nian+'0'+yue+ri
else:
if (int(ri) < 10):
return nian+yue+'0'+ri
else:
return nian+yue+ri
def niancha_cal(date1, date2):
# 默认date1先于date2
if int(date1)<int(date2): # 交换两者顺序
temp = date1
date1 = date2
date2 = temp
if int(date1[4:6]) < int(date2[4:6]): # 判断月的大小关系
return int(date1[0:4])-int(date2[0:4])-1 # 不满周岁得减一
elif int(date1[4:6]) > int(date2[4:6]):
return int(date1[0:4])-int(date2[0:4])
else:
if int(date1[6:8]) < int(date2[6:8]): # 进一步判断“日”的大小关系
return int(date1[0:4]) - int(date2[0:4]) - 1 # 不满周岁得减一
else:
return int(date1[0:4]) - int(date2[0:4])
if __name__ == '__main__':
app = qapplication(sys.argv)
w = window()
w.show()
sys.exit(app.exec_())
到此这篇关于python+pyqt编写一个批量年龄计算工具的文章就介绍到这了,更多相关python计算年龄内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论