日期计算跳过周末
使用pandas计算一定日期内工作日的天数,周末天数,遇到周末向后延长对应天数
例如
'2022-06-2’到’2022-06-04’之间有一天不是工作日
def skip_weekend(start_date='2022-06-20', end_date='2022-06-27'):
"""跳过周末(忽略节假日)"""
import datetime
import arrow
import pandas as pd
if not isinstance(end_date, datetime.date):
end_date = arrow.get(end_date).date()
if not isinstance(start_date, datetime.date):
start_date = arrow.get(start_date).date()
everyday = (end_date - start_date).days + 1 # 每天
weekday = len(pd.bdate_range(start_date, end_date)) # 工作日
day_off = everyday - weekday # 休息日
new_start_date = arrow.get(end_date).shift(days=+1).date()
new_end_date = arrow.get(end_date).shift(days=+day_off).date()
def over_day(new_start_date, new_end_date, day_off):
print(new_start_date, new_end_date, day_off)
weekday = len(pd.bdate_range(new_start_date, new_end_date))
print(weekday)
new_day_off = day_off - weekday
print(day_off)
if new_day_off != 0:
new_end_date = arrow.get(new_end_date).shift(days=+new_day_off).date()
return over_day(new_start_date, new_end_date, day_off)
return new_start_date, new_end_date, day_off
new_start_date, new_end_date, day_off = over_day(new_start_date, new_end_date, day_off)
return start_date, new_end_date
实例
a, b = skip_days_off('2022-06-2', '2022-06-4')
print(a, b)
输出结果
2022-06-02 2022-06-06
日期计算跳过休息日(包含周末和节假日)
使用pandas 自定义节假日规则,补班规则,一定日期内遇到节假日或者周末延后对应天数
例如
2022-10-01
到 2022-10-07
中间有 7
天休息日;而且10月8日(星期六)、10月9日(星期日)上班
"""
获取地址:https://www.gov.cn/zhengce/content/2021-10/25/content_5644835.htm
一、元旦:2022年1月1日至3日放假,共3天。
二、春节:1月31日至2月6日放假调休,共7天。1月29日(星期六)、1月30日(星期日)上班。
三、清明节:4月3日至5日放假调休,共3天。4月2日(星期六)上班。
四、劳动节:4月30日至5月4日放假调休,共5天。4月24日(星期日)、5月7日(星期六)上班。
五、端午节:6月3日至5日放假,共3天。
六、中秋节:9月10日至12日放假,共3天。
七、国庆节:10月1日至7日放假调休,共7天。10月8日(星期六)、10月9日(星期日)上班。
"""
import arrow
import pandas as pd
from pandas.tseries.offsets import CustomBusinessDay
import datetime
class SkipDaysOff:
# 假期规则 国务院每年会发放假期通知 http://www.gov.cn/
year = str(arrow.now().date().year) # 当前年份
holiday_rules = [year + '-01-01', year + '-01-02', year + '-01-03',
year + '-01-31', year + '-02-01', year + '-02-02', year + '-02-03', year + '-02-04',
year + '-02-05', year + '-02-06',
year + '-04-03', year + '-04-04', year + '-04-05',
year + '-04-30', year + '-05-01', year + '-05-02', year + '-05-03', year + '-05-04',
year + '-06-03', year + '-06-04', year + '-06-05',
year + '-09-10', year + '-09-11', year + '-09-12',
year + '-10-01', year + '-10-02', year + '-10-03', year + '-10-04', year + '-10-05',
year + '-10-06', year + '-10-07']
# 额外工作日
extra_workday = [year + '-01-29', year + '-01-30', year + '-04-02', year + '-04-24', year + '-05-07',
year + '-10-08', year + '-10-09']
c = CustomBusinessDay(holidays=holiday_rules)
def count_workday(self, start_day, end_day):
"""返回工作日天数,和休息日天数"""
everyday = [i.strftime('%Y-%m-%d') for i in arrow.Arrow.range('day', start_day, end_day)]
workday = len(pd.date_range(start=start_day, end=end_day, freq=self.c))
extra_workday_len = len(set(everyday) & set(self.extra_workday))
workday_num = workday+extra_workday_len
day_off_num = len(everyday) - workday_num
return workday_num, day_off_num
def skip_days_off(self, start_date='2022-06-20', end_date='2022-06-27'):
"""跳过休息日 结束日期=原结束日期+休息日(天数)"""
if not isinstance(end_date, datetime.date):
end_date = arrow.get(end_date).datetime
if not isinstance(start_date, datetime.date):
start_date = arrow.get(start_date).datetime
# 休息日天数
day_off = self.count_workday(start_date, end_date)[1]
# 新增加天数的开始时间
new_start_date = arrow.get(end_date).shift(days=+1).datetime
# 新增加天数的结束时间
new_end_date = arrow.get(end_date).shift(days=+day_off).datetime
def over_day(new_start_date, new_end_date, day_off):
"""
新结束时间将一直增加新休息日;
新增加天数中工作日天数等于缺少的休息日天数时,结束
"""
weekday = self.count_workday(new_start_date, new_end_date)[0]
new_day_off = day_off - weekday
if new_day_off != 0:
new_end_date = arrow.get(new_end_date).shift(days=+new_day_off).datetime
return over_day(new_start_date, new_end_date, day_off)
return new_start_date, new_end_date, day_off
new_start_date, new_end_date, day_off = over_day(new_start_date, new_end_date, day_off)
return start_date.date(), new_end_date.date()
实例
a, b = SkipDaysOff().skip_days_off('2022-10-01', '2022-10-07')
print(a, b)
输出结果
2022-10-01 2022-10-14
输出结果将,额外的工作日也计算进去了,跳过n天休息日,增加n天工作日