计算时间间隔的持续时间,同时删除某些时间跨度

时间:2018-12-20 15:44:18

标签: r lubridate

假设我们有一个跨越几天的间隔(下图中的间隔“ A”)。

library(lubridate)
int <- interval("2018-01-01 22:00:00", "2018-01-04 10:00:00")

几个小时后,我得到

as.period(int, unit = "hours")
"60H 0M 0S"

现在,我要减去所有非工作时间,这里是该时间间隔的16:00-08:00(灰色),即仅保留蓝色部分(08:00-16:00),然后再次,计算剩余小时数(请参见下图中的“ B”),即8 + 8 + 2 = 18小时。

enter image description here

一种方法是创建一个我要保留的区间列表,该区间跨越整个区间,然后计算交点。 (下面的代码当然可以使用下限/上限/ seq功能等以编程方式进行设置。)

int_keep <- list(
  interval("2018-01-01 08:00:00", "2018-01-01 16:00:00"),
  interval("2018-01-02 08:00:00", "2018-01-02 16:00:00"),
  interval("2018-01-03 08:00:00", "2018-01-03 16:00:00"),
  interval("2018-01-04 08:00:00", "2018-01-04 16:00:00"),
  interval("2018-01-05 08:00:00", "2018-01-05 16:00:00")
)

l <- lapply(int_keep, function(x) intersect(x, int))
mns <- sapply(l, as.numeric)    # returns seconds
sum(mns, na.rm = T) / 60 / 60   # sum of intersections in hours
[1] 18

虽然可行,但对我来说却显得很笨拙。这样做会是一个不太繁琐的方法吗?

1 个答案:

答案 0 :(得分:1)

df <- data.frame(DateTime=seq.POSIXt(as.POSIXct("2018-01-01 22:00:00"), as.POSIXct("2018-01-04 10:00:00"), by = "1 hour"))
head(df)
#DateTime
#1 2018-01-01 22:00:00
#2 2018-01-01 23:00:00
#3 2018-01-02 00:00:00
#4 2018-01-02 01:00:00
#5 2018-01-02 02:00:00
#6 2018-01-02 03:00:00

#you want the hours worked between A and B
A <-format(strptime("8:00:00", "%H:%M:%S"),"%H:%M:%S")
B <-format(strptime("16:00:00", "%H:%M:%S"),"%H:%M:%S")
#a simple ifelse statement to assign a value of 1 to column "value" if the time is between 8 and 16 or a 0 if it's not: 
df$value<-ifelse((format(df[1],"%H:%M:%S")>A & format(df[1],"%H:%M:%S")<=B),1,0)
 tail(df)
 #DateTime DateTime
 #56 2018-01-04 05:00:00        0
 #57 2018-01-04 06:00:00        0
 #58 2018-01-04 07:00:00        0
 #59 2018-01-04 08:00:00        0
 #60 2018-01-04 09:00:00        1
 #61 2018-01-04 10:00:00        1
#now taking the column sum of the value column will give you the total hours worked: 
TotalHoursWorked<-colSums(df$value)
TotalHoursWorked
#DateTime 
 # 18