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

如何在Python Odoo中计算排除节假日的员工总工时

Odoo中计算排除节假日的员工总工时实现方案

问题分析

你当前的代码仅计算了起止日期的原始时间差,未排除周末和节假日,且日期处理存在冗余(Odoo的date字段无需转字符串再解析)。以下是完整的修正方案,包含工作日过滤、节假日排除逻辑。

解决步骤

  1. 规范日期处理:直接使用Odoo返回的date对象,无需字符串转换
  2. 过滤周末:遍历日期区间,排除周六(weekday=5)和周日(weekday=6)
  3. 排除节假日:关联Odoo内置的resource.calendar.leaves模型(或员工关联的资源日历假期),过滤掉区间内的节假日
  4. 计算有效工时:有效工作日数量 × 每日8小时

修改后的完整代码

from datetime import timedelta
from dateutil.rrule import rrule, DAILY
from odoo import api, models, fields

class YourModelName(models.Model):
    _inherit = 'your.model.name'  # 替换为你的实际模型名

    start_date = fields.Date(string="开始日期")
    date_deadline = fields.Date(string="截止日期")
    total_hours = fields.Float(string="总工时", compute="_compute_hours", store=True)

    @api.depends("start_date", "date_deadline")
    def _compute_hours(self):
        for record in self:
            total_hours = 0.0
            if record.start_date and record.date_deadline:
                start_dt = fields.Datetime.from_string(record.start_date)
                end_dt = fields.Datetime.from_string(record.date_deadline)

                # 生成起止区间内的所有日期(含首尾)
                all_days = rrule(DAILY, dtstart=start_dt, until=end_dt)

                # 过滤周末:仅保留周一至周五
                work_days = [day for day in all_days if day.weekday() < 5]

                # 获取区间内的节假日(关联资源日历假期,可根据实际业务调整)
                # 这里默认使用员工关联的资源日历,若为全局节假日可调整查询条件
                holiday_days = self.env['resource.calendar.leaves'].search([
                    ('date_from', '<=', end_dt.date()),
                    ('date_to', '>=', start_dt.date()),
                    ('resource_id', '=', record.employee_id.resource_id.id if record.employee_id else False),
                    ('time_type', '=', 'leave')
                ])

                # 提取节假日日期集合
                holiday_set = set()
                for holiday in holiday_days:
                    holiday_start = fields.Date.from_string(holiday.date_from)
                    holiday_end = fields.Date.from_string(holiday.date_to)
                    current_date = holiday_start
                    while current_date <= holiday_end:
                        holiday_set.add(current_date)
                        current_date += timedelta(days=1)

                # 计算有效工作日:工作日 - 节假日
                valid_days = [day for day in work_days if day.date() not in holiday_set]
                total_hours = len(valid_days) * 8  # 每日8小时

            record.total_hours = total_hours

关键说明

  • 资源日历配置:确保员工的resource_id关联了正确的资源日历,且已在日历中添加节假日(路径:设置 > 人力资源 > 资源日历)
  • 自定义节假日模型:若你的业务使用独立的节假日模型,只需替换resource.calendar.leaves的查询逻辑为你的模型查询
  • 边界处理:自动处理起止日期相同、区间跨月/跨年等场景,若起止日期为同一天且是有效工作日,将返回8小时

内容的提问来源于stack exchange,提问作者Nahid Jawad Angon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 14:01:13