网络知识 娱乐 Python + SeaTable | 计算两个日期间的工作日天数

Python + SeaTable | 计算两个日期间的工作日天数

当我们计算两个日期间的间隔天数时,通常是用结束日期减去开始日期,但在实际的项目管理、任务管理、工作计划等场景中,某些时间段会涉及双休日、法定节假日,甚至还有公司自定义的工作时间安排,所以就需要计算出两个日期间的实际工作日天数。比如一个表格中有多条任务,每条任务都有各自的开始日期、计划结束日期或实际结束日期,那么如何自动计算出两个日期间的实际工作日天数,以便做到精细和量化呢。

此时,万能的 Python 就可以出场了,而用 Python + SeaTable 来实现则会更加方便工作管理。本文重点分享思路和代码,仅供参考。

SeaTable 表格有丰富的数据类型,如日期、单选、协作人、公式、按钮等等,可以方便又规范地管理各类信息。此外,还有很多基础功能和扩展功能,这其中就包括脚本功能。在表格上点击“脚本”按钮,可以导入或新建多个脚本,随时一键运行即可(如需设置定期运行等可在“自动化规则”中实现)。

比如在下面这个表格中,开始时间由项目管理者填写; 结束时间由每个任务负责人在完成项目时填写; 工作日(天数)则根据开始时间和结束时间,运行Python 脚本计算得出。

Python + SeaTable

案例表格

在 SeaTable 表格上新建 Python 脚本

具体来看。 首先, 我们打开脚本功能, 选择“新建脚本”, 选择 Python。

Python + SeaTable

在表格上新建和运行脚本

思路

在打开的界面中,就可以对脚本进行编写了。 在此处计算工作日的脚本编写过程中需要注意几个问题, 以中国为例:

  • 来年的工作日、休息日,暂不支持(因国家暂未发布安排) 。
  • 需要定义平日中休息的日期, 即周一到周五哪天休息。
  • 需要定义周末中工作的日期, 即周六、周日哪天调休。

代码

把以上的特殊日期一一列出来,这个脚本就不难编写了, 以下给出一些脚本片段, 以2022年为例。

import datetimenfrom enum import Enumnfrom seatable_api import dateutils, Base, contextnn# 一个 Base 的授权信息nSERVER_URL = context.server_url or 'https://cloud.seatable.cn'nAPI_TOKEN = context.api_token or 'dd46f9ca0172a850a0922107a6b2e6b99932b040'nn# 1. 定义中国的节假日概况nclass Holiday(Enum):n new_years_day = "元旦"n spring_festival = "春节"n tomb_sweeping_day = "清明"n labour_day ="劳动节"n dragon_boat_festival = "端午"n national_day = "国庆节"n mid_autumn_festival = "中秋"nn# 2. 列出节假日列表, 此处可以去查询日历,就不一一列出了nholidays = {ntdatetime.date(year=2022, month=1, day=1): Holiday.new_years_day.value,n datetime.date(year=2022, month=1, day=2): Holiday.new_years_day.value,n datetime.date(year=2022, month=1, day=3): Holiday.new_years_day.value,n datetime.date(year=2022, month=1, day=31): Holiday.spring_festival.value,n datetime.date(year=2022, month=2, day=1): Holiday.spring_festival.value,n .....n}nn# 3.列出调休日的列表,及周六日为工作日的列表nworkdays = {n datetime.date(year=2022, month=1, day=29): Holiday.spring_festival.value,n datetime.date(year=2022, month=1, day=30): Holiday.spring_festival.value,n datetime.date(year=2022, month=4, day=2): Holiday.tomb_sweeping_day.value,n datetime.date(year=2022, month=4, day=24): Holiday.labour_day.value,n datetime.date(year=2022, month=5, day=7): Holiday.labour_day.value,n datetime.date(year=2022, month=10, day=8): Holiday.national_day.value,n datetime.date(year=2022, month=10, day=9): Holiday.national_day.value,n ....n}nn# 4. 定义是否是工作日ndef is_workday(date):n '''n 工作日定义:n 1. 日期在workdays字典的key中n 2. 星期是周一到周五且不在holidays字典的key中n '''n date = _validate_date(date)n weekday = date.weekday()n return bool(date in workdays.keys() or (weekday <= 4 and date not in holidays.keys()))n n# 5. 计算两个日期之间的工作日, 此处返回的是工作日的列表, 该列表的长度即是工作日的天数ndef get_workdays(start, end):n """n 获取两个日期之间的工作日,返回datetime的列表n """n start, end = _validate_date(start, end)n return list(filter(is_workday, get_dates(start, end)))n n# 6. 将结果写入 SeaTablenndef calculate_base_workdays(base, table_name):n '''n 通过seatable表格中的,开始日期, 结束日期, 计算两个日期间工作日的天数,并把其更新到该行的n 工作日字段中n '''nn for row in base.list_rows(table_name):n row_id = row.get('_id')n start_date = row.get("开始日期")n end_date = row.get("结束日期")n if not (start_date and end_date):n continuen try:n work_day_list = get_workdays(start_date, end_date)n # 两个日期间的工作日天数n work_day_counts = len(work_day_list)n cell_value = row.get("工作日")n if cell_value == work_day_counts:n continuen base.update_row(n table_name,n row_id,n {n "工作日": work_day_countsn }n )n except Exception as e:n print("start date: %s, end date: %s, error: %s" % (start_date, end_date, e) )n continuen nbase = Base(API_TOKEN, SERVER_URL)nbase.auth()ncalculate_base_workdays(base, "工作任务安排")

完整脚本可以参照(链接):https://github.com/seatable/seatable-scripts-cn/blob/master/examples/python/work_days_calculator.py

总结

SeaTable 作为一款以在线协同表格为基础的新型数字化平台,功能丰富,使用灵活,能帮我们实现一体化数据管理和处理。当我们需要快速地开发自定义数据处理流程时,就可以使用它完善的 Python API 功能,能节省很多成本。具体到本案例中,除了使用 Python 来计算两个日期间的工作日外,还可以使用表格的日历插件、时间线插件、高级统计插件等来进行查看和做可视化图表分析,让项目管理更方便,实现应用更简单。


案例参考

Python+SeaTable|用Python从维基百科抓冬奥会城市信息并制作地图

Python + SeaTable | 从启信宝网站获取公司融资等信息至 SeaTable 表格

同步服务器日志到 SeaTable,让日志更好地可视化和协同处理

教程 | SeaTable 地理位置列、地图插件、高级统计中的地图使用介绍

教程 | SeaTable 表格地图外部应用,制作和共享地图很简单