如何在工作时间内获得总小时数?
How to get total hours during working hours?
我在 pandas 中有两列是 UTC 时间戳:StartDate
和 EndDate
。这些日期适用于提交寻求帮助的任务。我正在尝试计算这些任务在工作时间内完成之前存在了多少小时。我公司的营业时间为太平洋标准时间周一至周五上午 8 点至下午 6 点。
我已经尝试进行这些计算,但 运行 遇到了问题。我不知道如何只在工作时间获得时间。我已经想出如何在整个时间段内计算时间,但我不知道如何继续进行。我目前的想法是在 for 循环中制作一个 if 语句并检查从我的计算中生成的 SLATable['Date Responded (Hours)']
列的每个值,但上次我尝试编辑值时单独在列中 python 抛出我一个错误。
#8-6 PST to UTC time
officeOpen = pd.Timestamp("8:00:00.000").tz_localize('US/Pacific').tz_convert('utc')
officeClose = pd.Timestamp("18:00:00.000").tz_localize('US/Pacific').tz_convert('utc')
#get data from sql server
SLATable = pd.read_sql_query(SqlQuery,conn)
#calculate Date Responded
SLATable['Date Responded (Hours)'] = SLATable['EndDate'] - SLATable['StartDate']
SLATable['Date Responded (Hours)'] = round(SLATable['Date Responded (Hours)']/np.timedelta64(1,'h'), 2)
目前,如果我使用上面的代码,如果它是在工作时间创建的,那么它适用于在创建当天完成的任何任务,但周一创建并在周二完成的任务将在工作时间之外工作工作时间。此外,如果任务是在办公时间以外创建的,它将收集时间,直到我们在工作时间内解决它。
这些计算不适用于周一至周五 8 点到 6 点的任何国家/地区的假期。
示例数据如果 运行 通过我的计算:
StartDate EndDate Date Responded (Hours)
2016-05-03 2016-05-03 0.13
15:51:11.850 15:59:13.017
2016-05-05 2016-05-06 17.64
23:01:51.023 16:40:21.350
如果计算正确,输出应该是什么:
StartDate EndDate Date Responded (Hours)
2016-05-03 2016-05-03 0.13
15:51:11.850 15:59:13.017
2016-05-05 2016-05-06 0.32
23:01:51.023 16:40:21.350
第一步是定义一个 BusinessHour 偏移量,使用适当的
开始/结束时间(稍后会用到):
bhOffs = pd.offsets.BusinessHour(start='08:00', end='18:00')
然后定义一个从 UTC 时间计算业务时间的函数,使用
正确的时区偏移量:
def BusTime(ts, hOffs, fwd):
'''Compute business time. Params:
ts - UTC time (string or Timestamp)
hOffs - Hour offset (int)
fwd - Roll variant (forward / backward, bool)
'''
tsWrk = ts if type(ts) == 'str' else pd.Timestamp(ts)
tsOffs = tsWrk + np.timedelta64(hOffs, 'h')
if fwd: # Roll if on End of Day
tsRoll = bhOffs.rollforward(tsOffs + np.timedelta64(1, 'ms'))
else: # Don't roll if on End of Day
tsRoll = bhOffs.rollforward(tsOffs - np.timedelta64(1, 'ms'))
return tsRoll if tsRoll.day != tsOffs.day else tsOffs
最后一步,定义一个计算营业时间的函数:
def BusHrs(ts1, ts2, hOffs=0):
'''Compute business hours between 2 DateTimes. Params:
ts1, ts2 - From / To (UTC, Timestamp or string)
hOffs - Hour offset (int)
'''
t1 = BusTime(ts1, hOffs, True)
t2 = BusTime(ts2, hOffs, False)
bHrs = pd.date_range(start=t1.floor('h'), end=t2.floor('h'),
freq=bhOffs, closed='left').size
frac1 = t1 - t1.normalize() - np.timedelta64(t1.hour, 'h')
frac2 = t2 - t2.normalize() - np.timedelta64(t2.hour, 'h')
return bHrs + (frac2 - frac1) / np.timedelta64(1, 'h')
想法是:
- 将 UTC 开始/结束时间转换为正确的时区。
- 在本地开始/结束时间之间生成一个 DatetimeIndex,
四舍五入为整小时。
- 从该索引的大小中获取完整小时数。
- 从开始/结束时间按小时的小数部分更正。
我对你的数据进行了测试:
BusHrs('2016-05-03 15:51:11.850', '2016-05-03 15:59:13.017', -7)
- 结果
0.1336575.
BusHrs('2016-05-05 23:01:51.023', '2016-05-06 16:40:21.350', -7)
- 结果
3.6417574999999998.
第二个结果和你预期的结果不一样,但是原理
如下:
- 开始时间:
2016-05-05 23:01
UTC 是 2016-05-05 16:01
(太平洋时间)。
- 结束时间:
2016-05-06 16:40
UTC 是 2016-05-06 09:40
(太平洋)。
- 2016-05-05 的工作时间差不多 2 小时(最多 18:00)。
- 2016-05-06 的工作时间差不多 1 小时 40 米(来自 8:00)。
- 两个工作时间的总和只是 3.64....
我没有在你的第三组开始/结束时间测试这个功能,因为
估计是哪里出了问题(实际工作时间远远超过
您的预期结果)。
我在 pandas 中有两列是 UTC 时间戳:StartDate
和 EndDate
。这些日期适用于提交寻求帮助的任务。我正在尝试计算这些任务在工作时间内完成之前存在了多少小时。我公司的营业时间为太平洋标准时间周一至周五上午 8 点至下午 6 点。
我已经尝试进行这些计算,但 运行 遇到了问题。我不知道如何只在工作时间获得时间。我已经想出如何在整个时间段内计算时间,但我不知道如何继续进行。我目前的想法是在 for 循环中制作一个 if 语句并检查从我的计算中生成的 SLATable['Date Responded (Hours)']
列的每个值,但上次我尝试编辑值时单独在列中 python 抛出我一个错误。
#8-6 PST to UTC time
officeOpen = pd.Timestamp("8:00:00.000").tz_localize('US/Pacific').tz_convert('utc')
officeClose = pd.Timestamp("18:00:00.000").tz_localize('US/Pacific').tz_convert('utc')
#get data from sql server
SLATable = pd.read_sql_query(SqlQuery,conn)
#calculate Date Responded
SLATable['Date Responded (Hours)'] = SLATable['EndDate'] - SLATable['StartDate']
SLATable['Date Responded (Hours)'] = round(SLATable['Date Responded (Hours)']/np.timedelta64(1,'h'), 2)
目前,如果我使用上面的代码,如果它是在工作时间创建的,那么它适用于在创建当天完成的任何任务,但周一创建并在周二完成的任务将在工作时间之外工作工作时间。此外,如果任务是在办公时间以外创建的,它将收集时间,直到我们在工作时间内解决它。
这些计算不适用于周一至周五 8 点到 6 点的任何国家/地区的假期。
示例数据如果 运行 通过我的计算:
StartDate EndDate Date Responded (Hours)
2016-05-03 2016-05-03 0.13
15:51:11.850 15:59:13.017
2016-05-05 2016-05-06 17.64
23:01:51.023 16:40:21.350
如果计算正确,输出应该是什么:
StartDate EndDate Date Responded (Hours)
2016-05-03 2016-05-03 0.13
15:51:11.850 15:59:13.017
2016-05-05 2016-05-06 0.32
23:01:51.023 16:40:21.350
第一步是定义一个 BusinessHour 偏移量,使用适当的 开始/结束时间(稍后会用到):
bhOffs = pd.offsets.BusinessHour(start='08:00', end='18:00')
然后定义一个从 UTC 时间计算业务时间的函数,使用 正确的时区偏移量:
def BusTime(ts, hOffs, fwd):
'''Compute business time. Params:
ts - UTC time (string or Timestamp)
hOffs - Hour offset (int)
fwd - Roll variant (forward / backward, bool)
'''
tsWrk = ts if type(ts) == 'str' else pd.Timestamp(ts)
tsOffs = tsWrk + np.timedelta64(hOffs, 'h')
if fwd: # Roll if on End of Day
tsRoll = bhOffs.rollforward(tsOffs + np.timedelta64(1, 'ms'))
else: # Don't roll if on End of Day
tsRoll = bhOffs.rollforward(tsOffs - np.timedelta64(1, 'ms'))
return tsRoll if tsRoll.day != tsOffs.day else tsOffs
最后一步,定义一个计算营业时间的函数:
def BusHrs(ts1, ts2, hOffs=0):
'''Compute business hours between 2 DateTimes. Params:
ts1, ts2 - From / To (UTC, Timestamp or string)
hOffs - Hour offset (int)
'''
t1 = BusTime(ts1, hOffs, True)
t2 = BusTime(ts2, hOffs, False)
bHrs = pd.date_range(start=t1.floor('h'), end=t2.floor('h'),
freq=bhOffs, closed='left').size
frac1 = t1 - t1.normalize() - np.timedelta64(t1.hour, 'h')
frac2 = t2 - t2.normalize() - np.timedelta64(t2.hour, 'h')
return bHrs + (frac2 - frac1) / np.timedelta64(1, 'h')
想法是:
- 将 UTC 开始/结束时间转换为正确的时区。
- 在本地开始/结束时间之间生成一个 DatetimeIndex, 四舍五入为整小时。
- 从该索引的大小中获取完整小时数。
- 从开始/结束时间按小时的小数部分更正。
我对你的数据进行了测试:
BusHrs('2016-05-03 15:51:11.850', '2016-05-03 15:59:13.017', -7)
- 结果 0.1336575.BusHrs('2016-05-05 23:01:51.023', '2016-05-06 16:40:21.350', -7)
- 结果 3.6417574999999998.
第二个结果和你预期的结果不一样,但是原理 如下:
- 开始时间:
2016-05-05 23:01
UTC 是2016-05-05 16:01
(太平洋时间)。 - 结束时间:
2016-05-06 16:40
UTC 是2016-05-06 09:40
(太平洋)。 - 2016-05-05 的工作时间差不多 2 小时(最多 18:00)。
- 2016-05-06 的工作时间差不多 1 小时 40 米(来自 8:00)。
- 两个工作时间的总和只是 3.64....
我没有在你的第三组开始/结束时间测试这个功能,因为 估计是哪里出了问题(实际工作时间远远超过 您的预期结果)。