判断两个日期间差多少个工作日(包含法定假日调休)及某一天是否为工作日(附python代码)

项目中账单每月扣款要考虑到工作日和休息日,故需要判断某一天是否为工作日或休息日,以及两个出账日之间的工作日间隔。
而每年假日办公布的假期是会变化的,通过下面的代码可以灵活获取每年的工作日休息日情况,可以直接使用,或者将数据存入各类数据库以供查询。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!usr/bin/python
# _*_coding:utf-8_*_
import sys
sys.path.append("..")
from datetime import datetime, timedelta
from dateutil import rrule
from dateutil.parser import parse


# 法定节假日是工作日的日期记录下来, 休息日是工作日的记录下来
hoilday_is_work = ['20180101', '20180215', '20180216', '20180219', '20180220', '20180221', '20180405', '20180406',
'20180430', '20180501', '20180618', '20180924', '20181001', '20181002 ', '20181003', '20181004',
'20181005']

week_2_work = ['20180211', '20180224', '20180408', '20180428', '20180929', '20180930']


# 计算两个日期间有多少个工作日
def workdays(start, end, holidays=0, days_off=None):
if days_off is None:
days_off = 5, 6
workdays = [x for x in range(7) if x not in days_off]
days = rrule.rrule(rrule.DAILY, dtstart=start, until=end, byweekday=workdays)
return days.count() - holidays - 1


# 获取月份头尾
def get_start_end_month(x):
the_year = datetime.today().strftime('%Y')
# for x in xrange(1, 13):
# dt_start = (datetime(int(the_year), x, 1)).strftime("%Y%m%d")
# if 12 == x:
# dt_end = (datetime(int(the_year), 12, 31)).strftime("%Y%m%d")
# else:
# dt_end = (datetime(int(the_year), x+1, 1) - timedelta(days=1)).strftime("%Y%m%d")
# print dt_start, dt_end
dt_start = (datetime(int(the_year), x, 1)).strftime("%Y-%m-%d")
if 12 == x:
dt_end = (datetime(int(the_year), 12, 31)).strftime("%Y-%m-%d")
else:
dt_end = (datetime(int(the_year), x+1, 1) - timedelta(days=1)).strftime("%Y-%m-%d")
return [dt_start, dt_end]


# 组合数据
def gen_data(day1, day2):
day1 = parse(day1)
day2 = parse(day2)
hoilday = 0
for x in range((day2 - day1).days + 1):
singledays = (day1 + timedelta(days=x)).strftime('%Y%m%d')
if singledays in hoilday_is_work:
hoilday += 1
if singledays in week_2_work:
hoilday -= 1
# print(singledays)
period_time = workdays(day1, day2, hoilday)
print(period_time)
return period_time


if __name__ == '__main__':
try:
day1 = '20180930'
day2 = '20181010'
gen_data(day1, day2)
except BaseException as e:
print(e)

# debit = 10
# balance = 28
# month = 2
# day1 = parse('201806{}'.format(debit))
# day2 = parse('201806{}'.format(balance))
# if balance > debit:
# day1 = parse('201807{}'.format(debit))
# print(day1, day2)
# period = day1 + relativedelta(months=month)
# print(period)

# hoilday = 0
# for x in range((day2 - day1).days + 1):
# singledays = (day1 + timedelta(days=x)).strftime('%Y%m%d')
# if singledays in hoilday_is_work:
# hoilday += 1
# if singledays in week_2_work:
# hoilday -= 1
# print(singledays)
# period = workdays(day1, day2, hoilday)
# print(period)