You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python计算排除周末的9-17点工作时长问题求助

解决Python计算跨天有效工作时长的问题

原代码的核心问题

  1. 掩码条件过于苛刻:原代码的mask要求起始时间≥9点、结束时间≤17点且两者都在工作日,直接排除了跨天、起始/结束在非工作时段的有效场景(比如你提供的示例,起始时间在非工作时段,直接被过滤)。
  2. 时长计算逻辑错误:直接用end-start转换小时数,完全没拆分每日的有效工作区间,也没排除非工作时间和周末。
  3. 数组初始化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 01:36:31