Рассчитать продолжительность временного интервала при удалении определенных промежутков времени

Предположим, у нас есть интервал, охватывающий несколько дней (интервал "А" на рисунке ниже).

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 часов.

Один из подходов состоит в том, чтобы создать список интервалов, которые я хочу сохранить, которые охватывают весь интервал, а затем вычислять пересечения. (Код ниже, конечно, может быть настроен программно с использованием функций floor / floor / 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 ответ

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 
Другие вопросы по тегам