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

Pandas计算当前时间与指定日期的营业时间差问题求助

解决营业时间差计算的性能与错误问题

嘿,我来帮你搞定这个问题!你遇到的两个核心问题——程序失败和耗时过长,其实都有明确的原因和解决方案,咱们一步步来拆解:

1. 先解决程序失败:参数顺序搞反了

你的BusHrs函数是计算从start到end的营业时间差,但你调用的时候传的是BusHrs(row['Current Date'], row['Updated Date'])——这里Current Date是2018年(晚的时间),Updated Date是2016年(早的时间),相当于让函数计算"未来到过去"的时间差,这肯定会出问题!

修正方法很简单,调换两个参数的顺序:

df['Time Since Last Update'] = df.apply(lambda row: BusHrs(row['Updated Date'], row['Current Date']), axis=1)

2. 再解决耗时过长:大时间跨度的性能优化

你看示例里的时间跨度是2年左右,businesstimedelta的默认计算方式是逐天遍历检查节假日和工作日,这么大的范围自然会慢到离谱。咱们可以换一种更高效的计算逻辑:先算完整工作天数的总小时,再加上首尾两天的零碎营业时间,不用逐天遍历。

优化后的BusHrs函数如下,速度会提升N倍:

import datetime
import pytz
import businesstimedelta
import holidays as pyholidays

workday = businesstimedelta.WorkDayRule(
    start_time=datetime.time(9),
    end_time=datetime.time(17),
    working_days=[0,1,2,3,4]
)
vic_holidays = pyholidays.AU(prov='VIC')
holidays = businesstimedelta.HolidayRule(vic_holidays)
businesshrs = businesstimedelta.Rules([workday, holidays])

def BusHrs(start, end):
    # 处理start >= end的边界情况
    if start >= end:
        return 0.0
    
    start_date = start.date()
    end_date = end.date()
    
    # 情况1:开始和结束是同一天
    if start_date == end_date:
        # 检查当天是否是工作日且非节假日
        if start_date.weekday() >=5 or start_date in vic_holidays:
            return 0.0
        # 计算当天的有效营业时间
        work_start = datetime.datetime.combine(start_date, workday.start_time)
        work_end = datetime.datetime.combine(start_date, workday.end_time)
        actual_start = max(start, work_start)
        actual_end = min(end, work_end)
        return (actual_end - actual_start).total_seconds() / 3600
    
    # 情况2:时间跨度跨多天
    # 计算总天数
    total_days = (end_date - start_date).days
    
    # 计算这段时间内的节假日数量
    holiday_count = sum(1 for date in vic_holidays if start_date <= date <= end_date)
    
    # 计算周末天数
    start_weekday = start_date.weekday()
    weekend_days = total_days //7 *2
    remaining_days = total_days %7
    for day in range(remaining_days):
        if (start_weekday + day) %7 >=5:
            weekend_days +=1
    
    # 完整工作天数 = 总天数 - 周末 - 节假日
    full_work_days = total_days - weekend_days - holiday_count
    full_work_hrs = full_work_days *8  # 每天8小时
    
    # 计算开始当天的剩余营业时间
    start_work_end = datetime.datetime.combine(start_date, workday.end_time)
    start_work_start = datetime.datetime.combine(start_date, workday.start_time)
    if start >= start_work_end:
        start_hrs =0.0
    elif start <= start_work_start:
        start_hrs =8.0
    else:
        start_hrs = (start_work_end - start).total_seconds()/3600
    
    # 计算结束当天的营业时间
    end_work_start = datetime.datetime.combine(end_date, workday.start_time)
    end_work_end = datetime.datetime.combine(end_date, workday.end_time)
    if end <= end_work_start:
        end_hrs =0.0
    elif end >= end_work_end:
        end_hrs =8.0
    else:
        end_hrs = (end - end_work_start).total_seconds()/3600
    
    # 总时间 = 完整工作小时 + 开始当天剩余 + 结束当天时间 - 8(因为完整工作天包含了首尾两天的全天,要减去重复计算的部分)
    total_hrs = full_work_hrs + start_hrs + end_hrs -8.0
    
    return total_hrs

3. 额外注意:时区一致性问题

如果你的Current Date是带时区的datetime,而Updated Date是不带时区的naive datetime,这会导致datetime运算出错。建议统一所有日期的时区:

# 统一转换为墨尔本时区
melb_tz = pytz.timezone('Australia/Melbourne')
df['Updated Date'] = df['Updated Date'].apply(lambda x: melb_tz.localize(x, is_dst=None))
df['Current Date'] = df['Current Date'].apply(lambda x: melb_tz.localize(x, is_dst=None))

按照这几步操作,应该就能解决你的问题了——既不会报错,计算速度也会快很多!

内容的提问来源于stack exchange,提问作者swifty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:51:09