首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >射灯:计算工作日和小时内两个日期之间的时间戳差(8-17)。

射灯:计算工作日和小时内两个日期之间的时间戳差(8-17)。
EN

Stack Overflow用户
提问于 2022-10-25 11:27:11
回答 2查看 62关注 0票数 0

我尝试使用datediff,但是它只给出了两个日期之间的时差。我只想得到工作日和工作时间内的工作时间。举例如下:

开始日期: 19/08/2022 09:42:13

截止日期: 22/08/2022 09:54:22

从Datediff收到的结果(“HH”,开始日期,结束日期)= 72.20

我想要的实际结果大概是。= 8.13

EN

回答 2

Stack Overflow用户

发布于 2022-10-27 09:36:18

好的,你指的是像NetWorkHours这样的东西,而不是天。(我不明白你对媒体的评论。)

假设您有一个数据表,其中一个列用于开始日期,一个列用于结束日期(这些数据类型是DateTime数据类型),那么您可以创建一个TERR表达式,该表达式将这两个日期作为输入,并生成若干工时作为输出。

我用这个答案作为开始:How to calculate networkdays minus holidays between 2 dates

但这不包括几个小时。这是我建议的解决方案。最初的想法是删除开始和结束的一天(这是不完整的天数),并计算整日减去周末的数量,就像以前的解决方案一样。然后把它乘以一天中的工作时间。然后用第一天和最后一天计算工作时间。然后把这两个加在一起。

创建TERR表达式函数(从菜单数据>数据函数属性>表达式函数)

代码语言:javascript
运行
复制
#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是您的原始列。

票数 0
EN

Stack Overflow用户

发布于 2022-10-28 12:14:46

我以前的回答不起作用,主要有两个原因。首先,我试着修改一个有效满天的现有答案,但在将其扩展到小数日(例如,如果我的开始日期或结束日期相同,如果它们在周末下降等)时,有太多的边界情况。其次,TERR表达式函数期望使用向量化的输入,这实际上并不适用于有如此多例外的输入值的场景。

我认为,如果我创建一个TERR数据函数来输出一个全新的表,那么现在(至少对我的示例来说)它是可行的。我使用R库data.table来提高效率。我对算法进行了大量修改,将这些步骤向量化为一个临时数据表(schedule_df)。也许有更聪明的方法,但我没有找到。

您可能只需通过修改I/O输出一列。

在这里,希望它能帮上忙:

代码语言:javascript
运行
复制
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']])]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74193339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档