Python计算排除周末的9-17点工作时长问题求助
解决Python计算跨天有效工作时长的问题
原代码的核心问题
- 掩码条件过于苛刻:原代码的
mask要求起始时间≥9点、结束时间≤17点且两者都在工作日,直接排除了跨天、起始/结束在非工作时段的有效场景(比如你提供的示例,起始时间在非工作时段,直接被过滤)。 - 时长计算逻辑错误:直接用
end-start转换小时数,完全没拆分每日的有效工作区间,也没排除非工作时间和周末。 - 数组初始化bug:
result.fill(np.nan)返回的是新数组,原result并未被赋值为NaN,会导致未匹配mask的位置保留初始垃圾值。
正确实现方案
要准确计算有效工作时长,需要逐个日期拆分区间,过滤周末后计算每日的有效交集时长,再累加总和:
import pandas as pd import numpy as np def calculate_work_hours(start, end): # 处理空值或起始时间晚于结束时间的无效情况 if pd.isna(start) or pd.isna(end) or start >= end: return np.nan # 生成两个时间点覆盖的所有日期 dates = pd.date_range(start.date(), end.date(), freq='D') total_hours = 0.0 for date in dates: # 跳过周末(周六、周日) if date.weekday() >= 5: continue # 定义当日的工作时段:9:00 - 17:00 work_start = pd.Timestamp(date) + pd.Timedelta(hours=9) work_end = pd.Timestamp(date) + pd.Timedelta(hours=17) # 计算当前日期内的有效时间交集 interval_start = max(start, work_start) interval_end = min(end, work_end) # 若存在有效交集,累加时长(转换为小时) if interval_start < interval_end: duration = (interval_end - interval_start).total_seconds() / 3600 total_hours += duration # 保留两位小数,匹配预期输出格式 return round(total_hours, 2) # 测试你的示例 start_series = pd.Series([pd.to_datetime('2017-07-11 19:33:00')]) end_series = pd.Series([pd.to_datetime('2017/07/12 12:01:00')]) # 批量计算每一对时间的有效时长 result = pd.Series([calculate_work_hours(s, e) for s, e in zip(start_series, end_series)]) print(result) # 输出:0 3.02,符合预期
代码说明
- 对每个日期先判断是否为工作日,跳过周末;
- 针对工作日,取出当日的工作时段,再和输入的起止时间取交集,计算该日的有效时长;
- 累加所有工作日的有效时长,最终返回保留两位小数的结果。
内容的提问来源于stack exchange,提问作者LukeWarm
相关产品推荐
相关产品推荐

