Python业务工作时长计算函数的修改优化及输入适配需求
Python工作时长计算函数修改方案
需求说明
编写无需类定义的原生Python函数,实现业务工作时长计算,需支持小时单位输出,并适配以下输入格式:
get_work_hours("2019-12-02 09:30:00", "2019-12-07 12:15:00", worktiming=[9, 17])
原代码核心问题分析
- 输入处理错误:直接将字符串输入当作datetime对象操作,未做格式解析
- 对象初始化错误:
dt_start = datetime1.datetime属于非法写法,无法正确获取datetime实例 - 缺失依赖函数:未定义
is_weekend函数,且周末判断逻辑错误(Python的weekday()返回0-6,对应周一到周日,原代码的[6,7]不符合规范) - 日期循环逻辑漏洞:
current_day == dt_start会因时间部分差异导致判断失效,无法正确计算首日时长 - 边界时间处理错误:首尾日的工作时段修正存在日期参数误用,导致时长计算偏差
- 输出单位不符合要求:仅返回分钟数,未支持小时计算
修改后的完整代码
import datetime def get_work_hours(start_str, end_str, worktiming=[9, 17]): # 解析输入时间字符串为datetime对象,捕获格式错误 try: dt_start = datetime.datetime.strptime(start_str, "%Y-%m-%d %H:%M:%S") dt_end = datetime.datetime.strptime(end_str, "%Y-%m-%d %H:%M:%S") except ValueError: raise ValueError("输入时间格式错误,请使用'YYYY-MM-DD HH:MM:SS'格式") day_hours = worktiming[1] - worktiming[0] day_seconds = day_hours * 3600 # 单个工作日的总秒数 worktime_in_seconds = 0 # 处理结束时间早于开始时间的无效场景 if dt_end <= dt_start: return 0.0 # 定义周末判断逻辑:周六(5)、周日(6)为周末 def is_weekend(dt): return dt.weekday() in [5, 6] if dt_start.date() == dt_end.date(): # 同一天内的工作时长计算 if is_weekend(dt_start): return 0.0 # 修正开始时间至上班时段 work_start = datetime.datetime(dt_start.year, dt_start.month, dt_start.day, worktiming[0], 0) actual_start = max(dt_start, work_start) # 修正结束时间至下班时段 work_end = datetime.datetime(dt_end.year, dt_end.month, dt_end.day, worktiming[1], 0) actual_end = min(dt_end, work_end) # 修正后无有效工作时长则返回0 if actual_start >= actual_end: return 0.0 worktime_in_seconds = (actual_end - actual_start).total_seconds() else: # 跨多天的工作时长计算 # 处理第一天的有效时长 if not is_weekend(dt_start): work_start = datetime.datetime(dt_start.year, dt_start.month, dt_start.day, worktiming[0], 0) actual_start = max(dt_start, work_start) work_end = datetime.datetime(dt_start.year, dt_start.month, dt_start.day, worktiming[1], 0) if actual_start < work_end: worktime_in_seconds += (work_end - actual_start).total_seconds() # 处理中间完整的工作日 current_day = dt_start + datetime.timedelta(days=1) while current_day.date() < dt_end.date(): if not is_weekend(current_day): worktime_in_seconds += day_seconds current_day += datetime.timedelta(days=1) # 处理最后一天的有效时长 if not is_weekend(dt_end): work_start = datetime.datetime(dt_end.year, dt_end.month, dt_end.day, worktiming[0], 0) actual_start = max(work_start, datetime.datetime(dt_end.year, dt_end.month, dt_end.day, 0, 0)) work_end = datetime.datetime(dt_end.year, dt_end.month, dt_end.day, worktiming[1], 0) actual_end = min(dt_end, work_end) if actual_start < actual_end: worktime_in_seconds += (actual_end - actual_start).total_seconds() # 转换为小时单位,保留两位小数 return round(worktime_in_seconds / 3600, 2) # 测试示例 print(get_work_hours("2019-12-02 09:30:00", "2019-12-07 12:15:00", worktiming=[9, 17]))
关键修改说明
- 输入格式适配:新增字符串转datetime对象的逻辑,支持指定输入格式,同时捕获格式错误异常
- 修复核心逻辑错误:移除原代码中非法的datetime初始化写法,替换为正确的实例创建方式
- 完善周末判断:实现符合Python规范的周末识别逻辑,确保非工作日时长不被计算
- 优化循环逻辑:将日期比较从完整datetime对象改为仅比较日期部分,避免时间差异导致的逻辑失效
- 修正边界时间处理:统一首尾日的工作时段修正逻辑,确保仅计算有效工作时长
- 支持小时计算:最终返回值从分钟转换为小时,保留两位小数,满足需求
- 增强鲁棒性:新增无效时间顺序的判断,避免出现负数时长;添加异常处理提升代码容错性
内容的提问来源于stack exchange,提问作者user14269252
相关产品推荐
相关产品推荐

