周一至周五上午7点到下午5点我的工作时间。我想计算2列开始日期和结束日期的工作日和小时数。
这
Sno start date end date
1 4/6/2017 23:18 6/6/2017 21:23
2 4/6/2017 16:40 5/6/2017 2:52
3 5/6/2017 0:10 5/6/2017 4:10
4 5/6/2017 0:37 5/6/2017 7:16
5 5/6/2017 2:02 5/6/2017 10:48
要
Sno start date end date Bus Days Bus hours
1 4/6/2017 23:18 6/6/2017 21:23 1 10:00
2 4/6/2017 16:40 5/6/2017 2:52 0 0:20
3 5/6/2017 0:10 5/6/2017 4:10 0 0
4 5/6/2017 0:37 5/6/2017 7:16 0 0:16
5 5/6/2017 2:02 5/6/2017 10:48 0 3:48
我尝试过以下但有几个错误
from BusinessHours import BusinessHours as bh
df['bhours'] = (bh(df['start date'] , df['end date'] , worktiming=[7 , 17] , weekends=[6,7]).gethours()).astype('timedelta64[D]')
AttributeError: 'Series' object has no attribute 'days'
然后我尝试了另一种解决方案
df['bhours'] = len(pd.bdate_range(df['start date'] , df['end date'])).astype('timedelta64[D]')
TypeError: Cannot convert input [0 2017-04-06 18:52:00
df['bdays'] = (np.busday_count(df['start date'] , df['end date'])).astype('timedelta64[D]')
TypeError: Iterator operand 0 dtype could not be cast from dtype('<M8[ns]') to dtype('<M8[D]') according to the rule 'safe'
请帮助解决此问题。
答案 0 :(得分:0)
我写了这个方法,因为我发现营业时间包有语法错误。它应该工作正常。
import pandas as pd
import datetime
import numpy as np
df = pd.read_excel("/home/yasin/Documents/SametimeFileTransfers/final.xlsx")
df['sys_created_on'] = pd.to_datetime(df['sys_created_on'] )
df['resolved_at'] = pd.to_datetime(df['resolved_at'])
x = pd.to_datetime('2017-06-15 17:39')
y = pd.to_datetime('2017-06-15 18:00')
weekend = [6 ,7] # --> This is just for referral
time = [7 , 17] # --> This is just for referral
weekdays = [1 ,2, 3, 4 ,5]
def gethours(sdate , edate):
#Setting the start date
if sdate.isoweekday() == 6:
sdate += datetime.timedelta(days=2)
sdate = sdate.replace(hour = 7 , minute=0)
elif sdate.isoweekday() == 7:
sdate += datetime.timedelta(days=1)
sdate = sdate.replace(hour = 7 , minute=0)
elif ((sdate.isoweekday() in weekdays) & (sdate.hour > 17)):
sdate += datetime.timedelta(days=1)
if sdate.isoweekday() == 6:
sdate += datetime.timedelta(days=2)
sdate = sdate.replace(hour = 7 , minute=0)
else:
sdate = sdate.replace(hour = 7 , minute=0)
elif ((sdate.isoweekday() in weekdays) & (sdate.hour == 17) & (sdate.minute > 0)):
sdate += datetime.timedelta(days=1)
if sdate.isoweekday() == 6:
sdate += datetime.timedelta(days=2)
sdate = sdate.replace(hour = 7 , minute=0)
else:
sdate = sdate.replace(hour = 7 , minute=0)
elif ((sdate.isoweekday() in weekdays) & (sdate.hour < 7)):
sdate = sdate.replace(hour = 7 , minute=0)
else:
sdate
#Setting the end date
if edate.isoweekday() == 6:
edate += datetime.timedelta(days=2)
edate = edate.replace(hour = 7 , minute=0)
elif edate.isoweekday() == 7:
edate += datetime.timedelta(days=1)
edate = edate.replace(hour = 7 , minute=0)
elif ((edate.isoweekday() in weekdays) & (edate.hour > 17)):
edate += datetime.timedelta(days=1)
if edate.isoweekday() == 6:
edate += datetime.timedelta(days=2)
edate = edate.replace(hour = 7 , minute=0)
else:
edate = edate.replace(hour = 7 , minute=0)
elif ((edate.isoweekday() in weekdays) & (edate.hour == 17) & (edate.minute > 0) ):
edate += datetime.timedelta(days=1)
if edate.isoweekday() == 6:
edate += datetime.timedelta(days=2)
edate = edate.replace(hour = 7 , minute=0)
else:
edate = edate.replace(hour = 7 , minute=0)
elif ((edate.isoweekday() in weekdays) & (edate.hour < 7)):
edate = edate.replace(hour = 7 , minute=0)
else:
edate
#Appproximating the bus days
try:
days = np.busday_count(sdate , edate)
#Calculating the hours
if days == 0:
sec = (edate - sdate)
sec = sec.total_seconds()
hrs = sec // 3600
elif days > 0:
days = days - 1
hrs1 = days * 10
tdate1 = sdate.replace(hour = 17 , minute=0)
sec1 = (tdate1 - sdate)
sec1 = sec1.total_seconds()
hrss = sec1 // 3600
tdate2 = edate.replace(hour = 7 , minute=0)
sec2 = edate - tdate2
sec2 = sec2.total_seconds()
hrse = sec2 // 3600
hrs = hrs1 + hrss + hrse
except ValueError:
hrs = None
if hrs is None:
hrs = 0
return hrs