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

如何用Python计算两个datetime间工作日夜间、周末、节假日的分钟数?

解决方案

首先,我们需要将节假日字符串转换为date对象以便快速查询,同时编写辅助函数计算两个时间点之间的分钟数,再分别计算三个目标变量:

import datetime as dt

night_hours = [18, 19, 20, 21, 22, 23, 24, 0, 1, 2, 3, 4, 5, 6]
holidays = ["2023-04-01", "2023-04-05", "2023-04-11"]

dt_fmt = "%Y-%m-%d %H:%M"
start_dt = dt.strptime("2023-04-01 12:00", dt_fmt)
end_dt = dt.strptime("2023-04-15 23:00", dt_fmt)

# 将节假日转换为date集合,提升查询效率
holiday_dates = {dt.datetime.strptime(d, "%Y-%m-%d").date() for d in holidays}

def get_minutes_between(start, end):
    """计算两个datetime对象之间的分钟数,确保结果非负"""
    return max(0, int((end - start).total_seconds() // 60))

# 1. 计算所有节假日的总分钟数 minutes_of_all_the_holidays
minutes_of_all_the_holidays = 0
current_dt = start_dt
while current_dt < end_dt:
    current_date = current_dt.date()
    if current_date in holiday_dates:
        day_end = dt.datetime.combine(current_date + dt.timedelta(days=1), dt.time.min)
        segment_end = min(day_end, end_dt)
        minutes_of_all_the_holidays += get_minutes_between(current_dt, segment_end)
        current_dt = segment_end
    else:
        current_dt = dt.datetime.combine(current_date + dt.timedelta(days=1), dt.time.min)

# 2. 计算所有周末的总分钟数 minutes_of_all_the_weekends
minutes_of_all_the_weekends = 0
current_dt = start_dt
while current_dt < end_dt:
    current_date = current_dt.date()
    if current_date.weekday() >= 5:
        day_end = dt.datetime.combine(current_date + dt.timedelta(days=1), dt.time.min)
        segment_end = min(day_end, end_dt)
        minutes_of_all_the_weekends += get_minutes_between(current_dt, segment_end)
        current_dt = segment_end
    else:
        current_dt = dt.datetime.combine(current_date + dt.timedelta(days=1), dt.time.min)

# 3. 计算所有工作日夜间的总分钟数 minutes_of_all_workday_nights
minutes_of_all_workday_nights = 0
current_dt = start_dt
while current_dt < end_dt:
    current_date = current_dt.date()
    is_workday = current_date not in holiday_dates and current_date.weekday() < 5
    if not is_workday:
        current_dt = dt.datetime.combine(current_date + dt.timedelta(days=1), dt.time.min)
        continue
    
    # 处理当天18:00到当天结束的时段
    night_start_today = dt.datetime.combine(current_date, dt.time(18, 0))
    segment_start = max(current_dt, night_start_today)
    day_end = dt.datetime.combine(current_date + dt.timedelta(days=1), dt.time.min)
    segment_end = min(day_end, end_dt)
    minutes_of_all_workday_nights += get_minutes_between(segment_start, segment_end)
    
    # 处理次日0:00到6:00的时段,需次日也是工作日
    next_date = current_date + dt.timedelta(days=1)
    is_next_workday = next_date not in holiday_dates and next_date.weekday() < 5
    if is_next_workday:
        night_end_next = dt.datetime.combine(next_date, dt.time(6, 0))
        segment_start = max(day_end, start_dt)
        segment_end = min(night_end_next, end_dt)
        minutes_of_all_workday_nights += get_minutes_between(segment_start, segment_end)
    
    current_dt = dt.datetime.combine(next_date, dt.time(6, 0))

# 输出结果验证
print(f"工作日夜间总分钟数: {minutes_of_all_workday_nights}")
print(f"周末总分钟数: {minutes_of_all_the_weekends}")
print(f"节假日总分钟数: {minutes_of_all_the_holidays}")

代码说明

  • 节假日集合转换:把字符串格式的节假日转为date集合,实现O(1)快速查询。
  • 辅助函数:get_minutes_between确保计算的分钟数非负,避免时间顺序颠倒产生负数。
  • 节假日总分钟数:遍历区间内每一天,若当天是节假日,累加该天在区间内的有效分钟数。
  • 周末总分钟数:逻辑与节假日类似,通过weekday()判断是否为周六/周日即可。
  • 工作日夜间总分钟数:
    1. 先判断当天是否为工作日(非节假日且为周一至周五),非工作日直接跳过。
    2. 计算当天18:00到当天结束的有效分钟数。
    3. 若次日也是工作日,计算次日0:00到6:00的有效分钟数,避免将周末/节假日的凌晨时段计入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 02:25:00