我尝试使用datediff,但是它只给出了两个日期之间的时差。我只想得到工作日和工作时间内的工作时间。举例如下:
开始日期: 19/08/2022 09:42:13
截止日期: 22/08/2022 09:54:22
从Datediff收到的结果(“HH”,开始日期,结束日期)= 72.20
我想要的实际结果大概是。= 8.13
发布于 2022-10-27 09:36:18
好的,你指的是像NetWorkHours这样的东西,而不是天。(我不明白你对媒体的评论。)
假设您有一个数据表,其中一个列用于开始日期,一个列用于结束日期(这些数据类型是DateTime数据类型),那么您可以创建一个TERR表达式,该表达式将这两个日期作为输入,并生成若干工时作为输出。
我用这个答案作为开始:How to calculate networkdays minus holidays between 2 dates
但这不包括几个小时。这是我建议的解决方案。最初的想法是删除开始和结束的一天(这是不完整的天数),并计算整日减去周末的数量,就像以前的解决方案一样。然后把它乘以一天中的工作时间。然后用第一天和最后一天计算工作时间。然后把这两个加在一起。
创建TERR表达式函数(从菜单数据>数据函数属性>表达式函数)
#start and end of working hours
startShift=8
endShift=17
#fill vector with holiday dates if required. Example:
holidayDates <- c(as.Date('18/04/2022',format='%d/%m/%Y'),as.Date('29/08/2022',format='%d/%m/%Y'))
#count complete days excluding holidays and weekends
allDays = seq.Date(from=as.Date(input1)+1, to=as.Date(input2)-1, by=1)
nonHolidays = as.Date(setdiff(allDays, holidayDates), origin="1970-01-01")
weekends =nonHolidays[weekdays(nonHolidays) %in% c("Saturday", "Sunday")]
nonHolidaysWeekends = as.Date(setdiff(nonHolidays, weekends), origin="1970-01-01")
hoursCompleteDays = length(nonHolidaysWeekends) *(endShift-startShift)
#count worked hours for first and last day
beginTime = as.POSIXlt(input1)
beginHour = beginTime$hour + beginTime$min/60
endTime = as.POSIXlt(input2)
endHour = endTime$hour + endTime$min/60
hoursFirstAndLastDay = (endShift-beginHour)+(endHour-startShift)
#add together
output = hoursCompleteDays + hoursFirstAndLastDay 调用TERR表达式函数,例如TERR_netWorkingHours。这会给你工作的总时间。
使用它,创建一个计算列如下:
TERR_netWorkingHours(startDate,endDate)
其中startDate和endDate是您的原始列。
发布于 2022-10-28 12:14:46
我以前的回答不起作用,主要有两个原因。首先,我试着修改一个有效满天的现有答案,但在将其扩展到小数日(例如,如果我的开始日期或结束日期相同,如果它们在周末下降等)时,有太多的边界情况。其次,TERR表达式函数期望使用向量化的输入,这实际上并不适用于有如此多例外的输入值的场景。
我认为,如果我创建一个TERR数据函数来输出一个全新的表,那么现在(至少对我的示例来说)它是可行的。我使用R库data.table来提高效率。我对算法进行了大量修改,将这些步骤向量化为一个临时数据表(schedule_df)。也许有更聪明的方法,但我没有找到。
您可能只需通过修改I/O输出一列。
在这里,希望它能帮上忙:
suppressWarnings(suppressPackageStartupMessages(library(data.table)))
setDT(dt)
######## main function
netWorkingHours = function(input1, input2) {
#Helper function
extractHour = function(x) {
x = as.POSIXlt(x)
return (x$hour + x$min/60)
}
#prepare ---
dotimes=FALSE
#start and end of working hours
startShift=8
endShift=17
weekend = c('Saturday','Sunday')
#process
input1d = as.Date(input1)
input2d = as.Date(input2)
#list all days including start and end
allDays = seq.Date(from=input1d, to=input2d, by=1)
Ndays=length(allDays)
#flag included days: if they are not weekends
#can be expanded to holidays
include=ifelse(weekdays(allDays) %in% c('Saturday','Sunday'),0,1)
#start building schedule
schedule_df=data.table(day=allDays,include=include)
schedule_df$index=c(1:Ndays)
#identify boundary days
schedule_df[,boundary:=ifelse(index==1 | index==Ndays,index,0)]
#initialize working hours
schedule_df$start=startShift
schedule_df$end=endShift
#modify start and end hours for boundary days
schedule_df[boundary==1 & max(boundary)>1, start :=extractHour(input1)]
schedule_df[boundary==1 & max(boundary)>1, start :=extractHour(input1)]
schedule_df[boundary==1 & max(boundary)>1, end :=endShift]
schedule_df[boundary==1 & max(boundary)==1, start :=extractHour(input1)]
schedule_df[boundary==1 & max(boundary)==1, end :=extractHour(input2)]
schedule_df[boundary>1 , start :=startShift]
schedule_df[boundary>1 , end :=extractHour(input2)]
#shift start and end hours by shift limits
schedule_df[,start1:=sapply(start,function(x) max(startShift,x))]
schedule_df[,end1 :=sapply(end,function(x) min(endShift,x))]
#calculate worked hours for each day
schedule_df$worked_hours=0
schedule_df[include==1,worked_hours:=ifelse(end1>start1,end1-start1,0)]
Nincluded = nrow(schedule_df[include==1])
output = ifelse(Nincluded>0,sum(schedule_df[include==1,'worked_hours']),0)
return (output)
}
######################## main
dt[,workedHours:= mapply(netWorkingHours,dt[['date1']],dt[['date2']])]https://stackoverflow.com/questions/74193339
复制相似问题