最近在研究bpm系统,稍微整理一下请假表单的请假时间计算
这里只考虑了一天一个中休,且正常工作时间8小时,一周放两天
如果有法定节假日需要计算的话,需要用接口先获取法定节假日的数据,或者是先存一份节假日数据用于读取
整体思路
1.如果是同一天的话,考虑各种情况计算时间间隔
2.如果不是同一天的话,把时间分为三个部分
请假第一天/中间间隔天数/请假最后一天
3.用计算同一天有效时间的方式把第一天和最后一天算出来
4.加上中间间隔的完整的工作日时间
import datetime
import time
from datetime import timedelta
from dateutil import rrule
# 向上整点
def toptime(date):
return datetime.datetime.strptime(date.strftime('%Y-%m-%d')+' 00:00:00', '%Y-%m-%d %H:%M:%S')
# 向下整点
def uptime(date):
return datetime.datetime.strptime(date.strftime('%Y-%m-%d')+' 00:00:00', '%Y-%m-%d %H:%M:%S')+timedelta(days=1)
# 一天时间
def oneday_worktime(start_date,end_date,begin,rest,restend,end):
#开始时间和结束时间当天小时换算
opens = start_date.hour+(start_date.minute/60)
closes = end_date.hour+(end_date.minute/60)
if end_date>=start_date:
if closes==0:
closes = 24
#初始默认值为0
gap = 0
# 如果计算时间在非周末
if start_date.isoweekday() in [1,2,3,4,5]:
#如果在小于等于开始上班时间
if opens<=begin:
# 如果在中休前结束假期
if closes<=rest:
gap = closes-begin #直接减出来-----------------------------------------------------------------------------------------
#如果在晚上下班前结束
elif closes<=end:
gap = closes-begin-(restend-rest) #多减去一个中休-----------------------------------------------------------------------
# 如果在晚上下班后结束
else:
gap = rest-begin + end - restend #同一天又超过当天下班时间则为一整天工时-------------------------------------------------
#如果在上午中途请假
elif opens<=rest:
# 如果在中休前结束
if closes<=rest:
gap = closes-opens #直接减出来-----------------------------------------------------------------------------------------
# 如果在晚上下班前结束
elif closes<=end:
gap = closes-opens-(restend-rest) #多减去一个中休-----------------------------------------------------------------------
# 如果在晚上下班后结束
else:
gap = end-opens - (restend-rest) #------------------------------------------------------------------------------------------
#如果在中休结束之前请假
elif opens<=restend:
#如果下午提前回来
if closes<=end:
gap = closes-restend
else:
gap = end - restend
#如果在晚上下班前请假
elif opens<=end:
#如果下午提前回来
if closes<=end:
gap = closes-opens
else:
gap = end - opens
#如果乱选在晚上之后请假
else:
gap = 0
#如果不在工作日
else:
gap = 0
#如果前后时间相等,则扣掉默认赋予的24小时计算出来的时间
if end_date==start_date:
gap =0
return gap
def work_day(start_date,end_date):
days_off = 5, 6
workdays = [x for x in range(7) if x not in days_off]
secondly = rrule.rrule(rrule.DAILY, dtstart=start_date, until=end_date, byweekday=workdays)
seconds = secondly.count()
return seconds-1
# gap = 0
# start_date = datetime.datetime.strptime('2020-09-02 13:21:46', '%Y-%m-%d %H:%M:%S')
# end_date = datetime.datetime.strptime('2020-09-09 17:21:46', '%Y-%m-%d %H:%M:%S')
# begin =8.0
# rest =12
# restend =13.5
# end =17.5
def gap_time(start_date,end_date,begin=8.0,rest=12.0,restend=13.5,end=17.5):
#如果开始和结束都在同一天
if start_date.year==end_date.year and start_date.month==end_date.month and start_date.day==end_date.day:
gap = oneday_worktime(start_date,end_date,begin,rest,restend,end)
#如果不在同一天
else:
# 获取开始时间的下整点
first = uptime(start_date)
# 获取介素时间的上整点
last = toptime(end_date)
#计算第一天的时间
gap1 = oneday_worktime(start_date,first,begin,rest,restend,end)
#计算最后一天的时间
gap2 = oneday_worktime(last,end_date,begin,rest,restend,end)
#计算第一天之后,最后一天之前的天数
daynum = work_day(first,last)
gap3 = daynum*(rest-begin+end-restend)
gap = gap1+gap2+gap3
return gap
# print(gap_time(start_date,end_date))