当前位置:首页>python>Day18:时间旅行者!用Python轻松处理日期时间,自动算工龄、考勤、月报

Day18:时间旅行者!用Python轻松处理日期时间,自动算工龄、考勤、月报

  • 2026-09-15 14:46:41
Day18:时间旅行者!用Python轻松处理日期时间,自动算工龄、考勤、月报

还在Excel里手动拆分日期、计算间隔?Python让你一键搞定所有日期时间操作!

一、先看这个真实场景

周主任每个月都要做这些事:

  1. 从考勤系统导出打卡记录(几千行,日期格式乱七八糟)
  2. 要提取月份,统计每个月迟到人数
  3. 要计算工龄(入职日期到今天)
  4. 要筛选出本周过生日的员工
  5. 要按季度汇总项目支出

以前他用Excel:

  1. 日期格式不统一 → 分列 → 设置格式 ✓
  2. 提取月份 → 用MONTH函数 → 下拉 ✓
  3. 计算工龄 → DATEDIF函数 → 还要考虑闰年 ✓
  4. 筛选本周生日 → 写复杂公式 → 经常出错 ✓
  5. 季度汇总 → 先加辅助列 → 再透视表 ✓

一天又没了!

二、Python的“时间旅行”魔法

今天教你用Pandas处理日期时间,三行代码搞定上面所有事:

import pandas as pd# 模拟考勤数据(日期是字符串)df = pd.DataFrame({'姓名': ['张三', '李四', '王五', '赵六'],'打卡日期': ['2023-05-12', '2023/6/3', '2023.07.18', '2023-08-25'],'入职日期': ['2018-03-15', '2020-07-01', '2019-11-20', '2021-12-10']})# 魔法开始!统一转换为时间类型df['打卡日期'] = pd.to_datetime(df['打卡日期'])df['入职日期'] = pd.to_datetime(df['入职日期'])# 提取年份、月份、星期、季度df['打卡年份'] = df['打卡日期'].dt.yeardf['打卡月份'] = df['打卡日期'].dt.monthdf['星期几'] = df['打卡日期'].dt.day_name()df['季度'] = df['打卡日期'].dt.quarter# 计算工龄(到今天的天数)df['工龄(天)'] = (pd.Timestamp.now() - df['入职日期']).dt.daysprint("✅ 一键转换完成:")print(df[['姓名', '打卡日期', '打卡年份', '打卡月份', '星期几', '季度', '工龄(天)']])

看懂了吗?

  • pd.to_datetime():把乱七八糟的日期字符串统一转成Pandas时间类型
  • .dt.year/.month/.day/.day_name()/.quarter:像变魔术一样提取各种时间成分
  • 时间相减:直接得到时间间隔,再用.dt.days取天数

三、分解“魔法”:每步在干什么?

3.1 第一步:统一日期格式

df['打卡日期'] = pd.to_datetime(df['打卡日期'])
输入可以是:

'2023-05-12'、'2023/6/3'、'2023.07.18'、'12-May-2023'……

输出:

统一变成Pandas的Timestamp类型,显示为2023-05-12这样的标准格式。

如果遇到无法解析的日期,可以加参数errors='coerce',将无效日期转为NaT(缺失时间)。

3.2 第二步:提取时间成分

df['打卡年份'] = df['打卡日期'].dt.yeardf['打卡月份'] = df['打卡日期'].dt.monthdf['打卡日'] = df['打卡日期'].dt.daydf['星期几'] = df['打卡日期'].dt.day_name()      # 英文星期df['星期几中文'] = df['打卡日期'].dt.day_name(locale='zh_CN')  # 中文星期(需安装babel)df['季度'] = df['打卡日期'].dt.quarterdf['第几周'] = df['打卡日期'].dt.isocalendar().week  # 一年中的第几周

常用属性:

  • .year, .month, .day:年、月、日
  • .hour, .minute, .second:时、分、秒(如果有时间)
  • .dayofweek:星期几(0=周一,6=周日)
  • .day_name():星期名称(Monday等)
  • .quarter:季度(1-4)
  • .isocalendar().week:ISO周数

3.3 第三步:时间运算

# 计算两个日期的间隔df['入职天数'] = (df['打卡日期'] - df['入职日期']).dt.days# 计算年龄(假设今天是2024-01-01)今天 = pd.Timestamp('2024-01-01')df['年龄'] = (今天 - df['入职日期']).dt.days // 365  # 粗略# 更精确的年龄(考虑月份)df['年龄精确'] = (今天 - df['入职日期']).astype('timedelta64[Y]')  # 浮点数年

注意:时间相减得到的是Timedelta对象,可以用.dt.days取天数,.dt.seconds取秒数。

3.4 第四步:筛选特定时间范围

# 筛选2023年5月的数据df_5月 = df[df['打卡日期'].dt.month == 5]# 筛选2023年第二季度df_Q2 = df[(df['打卡日期'].dt.quarter == 2) & (df['打卡日期'].dt.year == 2023)]# 筛选本周(假设今天是2024-01-15,周一)本周开始 = pd.Timestamp('2024-01-15')本周结束 = 本周开始 + pd.Timedelta(days=6)df_本周 = df[(df['打卡日期'] >= 本周开始) & (df['打卡日期'] <= 本周结束)]

3.5 第五步:按时间分组统计

# 按月统计打卡次数月统计 = df.groupby(df['打卡日期'].dt.to_period('M'))['姓名'].count()# 按季度统计平均工龄季度统计 = df.groupby(df['打卡日期'].dt.quarter)['工龄(天)'].mean()
  • .dt.to_period('M'):将日期转换为月份周期(如2023-05),方便分组。

四、自己动手试试!

4.1 第一步:创建测试数据

import pandas as pd# 模拟员工信息(包含生日、入职日期)员工表 = pd.DataFrame({'姓名': ['张三', '李四', '王五', '赵六', '钱七'],'生日': ['1990-05-12', '1985-08-23', '1992-11-03', '1988-02-18', '1995-07-30'],'入职日期': ['2018-03-15', '2020-07-01', '2019-11-20', '2021-12-10', '2022-06-01']})print("📋 原始数据(日期是字符串):")print(员工表)

4.2 第二步:转换日期并提取信息

# 统一转换员工表['生日'] = pd.to_datetime(员工表['生日'])员工表['入职日期'] = pd.to_datetime(员工表['入职日期'])# 提取信息员工表['出生年份'] = 员工表['生日'].dt.year员工表['出生月份'] = 员工表['生日'].dt.month员工表['星座'] = 员工表['生日'].dt.month.map({1:'摩羯',2:'水瓶',3:'双鱼',4:'白羊',5:'金牛',6:'双子',                                             7:'巨蟹',8:'狮子',9:'处女',10:'天秤',11:'天蝎',12:'射手'})员工表['入职年份'] = 员工表['入职日期'].dt.year员工表['工龄(年)'] = ((pd.Timestamp.now() - 员工表['入职日期']).dt.days / 365.25).round(1)print("\n🎯 处理后数据:")print(员工表[['姓名', '生日', '星座', '入职年份', '工龄(年)']])

4.3 第三步:筛选本周过生日的员工

# 获取今天的月和日今天 = pd.Timestamp.now()本月 = 今天.month今日 = 今天.day# 筛选生日在本月的员工本月生日 = 员工表[员工表['生日'].dt.month == 本月]# 筛选生日在本周的(略复杂,需要计算日期范围,这里简化)print(f"\n🎂 本月过生日的员工:{本月生日['姓名'].tolist()}")

五、办公实战1:考勤月度统计表

import pandas as pdimport numpy as np# 模拟全年考勤记录(随机生成)np.random.seed(42)日期范围 = pd.date_range('2023-01-01', '2023-12-31', freq='D')姓名列表 = ['张三', '李四', '王五', '赵六', '钱七']# 随机生成打卡记录(每人每天一条)考勤数据 = []for 姓名 in 姓名列表:for 日期 in 日期范围:        状态 = np.random.choice(['正常', '迟到', '早退', '请假'], p=[0.85, 0.05, 0.05, 0.05])        考勤数据.append([姓名, 日期, 状态])df_考勤 = pd.DataFrame(考勤数据, columns=['姓名', '日期', '状态'])print("📋 考勤数据示例(前10行):")print(df_考勤.head(10))# 提取月份df_考勤['月份'] = df_考勤['日期'].dt.monthdf_考勤['月份名称'] = df_考勤['日期'].dt.month_name(locale='zh_CN')# 月度统计:每人每月迟到次数迟到统计 = df_考勤[df_考勤['状态'] == '迟到'].groupby(['姓名', '月份']).size().unstack(fill_value=0)print("\n📊 月度迟到统计表:")print(迟到统计)# 保存到Excel迟到统计.to_excel('月度迟到统计.xlsx')print("✅ 已保存为:月度迟到统计.xlsx")

六、办公实战2:自动计算工龄和退休年份

import pandas as pd# 员工信息(入职日期、出生日期)员工信息 = pd.DataFrame({'姓名': ['张三', '李四', '王五', '赵六'],'性别': ['男', '女', '男', '女'],'出生日期': ['1975-03-15', '1980-08-22', '1985-11-02', '1990-05-18'],'入职日期': ['2000-06-01', '2005-09-10', '2010-03-20', '2015-12-01']})# 转换日期员工信息['出生日期'] = pd.to_datetime(员工信息['出生日期'])员工信息['入职日期'] = pd.to_datetime(员工信息['入职日期'])# 计算年龄(截至今天)今天 = pd.Timestamp.now()员工信息['年龄'] = ((今天 - 员工信息['出生日期']).dt.days / 365.25).round(1)# 计算工龄(年)员工信息['工龄'] = ((今天 - 员工信息['入职日期']).dt.days / 365.25).round(1)# 计算退休年份(男60,女55)员工信息['退休年份'] = 员工信息.apply(    lambda row: row['出生日期'].year + (60 if row['性别'] == '男'else 55), axis=1)# 计算剩余工作年数员工信息['剩余工作年数'] = (员工信息['退休年份'] - 今天.year).round(1)print("\n🎯 员工工龄退休分析:")print(员工信息[['姓名', '年龄', '工龄', '退休年份', '剩余工作年数']])# 筛选未来5年内退休的员工五年内退休 = 员工信息[员工信息['剩余工作年数'] <= 5]print(f"\n⚠️ 未来5年内退休的员工:{五年内退休['姓名'].tolist()}")

七、办公实战3:财务报表季度汇总

import pandas as pd# 模拟全年销售记录销售数据 = pd.DataFrame({'日期': pd.date_range('2023-01-01', '2023-12-31', freq='D'),'销售额': np.random.randint(1000, 5000, size=365),'成本': np.random.randint(500, 3000, size=365)})# 添加季度、月份列销售数据['季度'] = 销售数据['日期'].dt.quarter销售数据['月份'] = 销售数据['日期'].dt.month# 计算利润销售数据['利润'] = 销售数据['销售额'] - 销售数据['成本']# 按季度汇总季度汇总 = 销售数据.groupby('季度').agg({'销售额': 'sum','成本': 'sum','利润': 'sum','日期': 'count'# 交易天数}).rename(columns={'日期': '交易天数'})# 添加季度名称季度汇总.index = ['Q1', 'Q2', 'Q3', 'Q4']print("\n📊 季度销售汇总表:")print(季度汇总)# 计算环比增长率季度汇总['销售额环比'] = 季度汇总['销售额'].pct_change() * 100print("\n📈 季度销售额环比增长率:")print(季度汇总['销售额环比'].round(1))# 保存季度汇总.to_excel('季度销售报告.xlsx')print("✅ 已保存为:季度销售报告.xlsx")

八、常用日期时间操作速查表

操作
代码
字符串转日期
pd.to_datetime(df['列'])
提取年份
df['日期'].dt.year
提取月份
df['日期'].dt.month
提取日
df['日期'].dt.day
提取星期(数字)
df['日期'].dt.dayofweek
(0=周一)
提取星期(名称)
df['日期'].dt.day_name()
提取季度
df['日期'].dt.quarter
提取周数
df['日期'].dt.isocalendar().week
日期加减
df['日期'] + pd.Timedelta(days=7)
计算间隔天数
(df['日期2'] - df['日期1']).dt.days
筛选某个月
df[df['日期'].dt.month == 5]
筛选某年
df[df['日期'].dt.year == 2023]
按月分组
df.groupby(df['日期'].dt.to_period('M')).sum()
按季度分组
df.groupby(df['日期'].dt.to_period('Q')).sum()

九、重点总结:今天你学会了什么?

✅ 核心技能

  1. pd.to_datetime() - 统一日期格式
  2. .dt 访问器 - 提取年、月、日、星期、季度
  3. 时间运算 - 计算间隔、年龄、工龄
  4. 时间筛选 - 按年月日范围过滤
  5. 时间分组 - 按月、季度汇总

✅ 办公应用场景

  1. 考勤统计:每月迟到次数、出勤率
  2. 人事管理:工龄、年龄、退休预警
  3. 财务分析:季度销售汇总、环比增长
  4. 日常办公:本周生日提醒、本月任务

✅ 效率对比

任务
Excel操作
Python代码
统一10种日期格式
分列+公式
1行代码
提取年月日星期
多个函数
1行代码
计算工龄(精确)
DATEDIF+考虑闰年
1行代码
按月统计
透视表+分组
1行代码

十、今日挑战:动手做!

任务1:生日提醒器

# 员工生日列表生日表 = pd.DataFrame({'姓名': ['张三', '李四', '王五', '赵六'],'生日': ['1990-05-12', '1985-08-23', '1992-11-03', '1988-02-18']})# 任务:提取月份和日,筛选出本月过生日的员工,并计算距离生日还有几天(忽略年份)

任务2:考勤异常统计

# 某月考勤数据(简化)考勤 = pd.DataFrame({'姓名': ['张三', '张三', '李四', '李四', '王五'],'日期': ['2024-01-05', '2024-01-06', '2024-01-05', '2024-01-06', '2024-01-05'],'状态': ['迟到', '正常', '正常', '早退', '旷工']})# 任务:将日期列转换为时间类型,按姓名统计每个人异常(迟到+早退+旷工)次数

任务3:合同到期提醒

# 合同信息合同表 = pd.DataFrame({'客户': ['A公司', 'B公司', 'C公司', 'D公司'],'签约日期': ['2022-03-15', '2022-07-01', '2023-01-10', '2023-05-20'],'合同期限月': [12, 6, 12, 3]  # 月份数})# 任务:计算合同到期日,筛选出未来30天内到期的合同,并显示剩余天数

十一、明日预告

明天学自动化办公终极武器——批量处理与邮件发送!

  • 如何用Python监控文件夹,新文件来了自动处理?
  • 如何把多个Excel合并后自动美化并发送邮件给领导?
  • 如何定时运行脚本,实现真正的“无人驾驶”?

真正的自动化办公,从明天开始!


回复「Py-Day」获取今日挑战题解及完整代码。

评论区作业:分享你工作中遇到的日期处理难题,或者晒出你的代码截图!👇

最新文章

随机文章