cmirian
cmirian

Reputation: 2253

r: How to calculate duration in hh:mm:s to a fixed time in hours but overlapping midnight

I have the following hh:mm:ss defined in df$times

     times
1 22:55:00
2 01:05:00
3 21:00:00

I want to calculate the duration from 20:00:00 to each of these times. However, some times are after midnight and the duration should in this case be estimated to 20:00:00 the 'following day`

Expected output

     times    new
1 22:55:00   2.92 
2 01:05:00   5.08
3 21:00:00  -1.00

Data

df <- structure(list(times = c("22:55:00", "01:05:00", "21:00:00")), class = "data.frame", row.names = c(NA, 
-3L))

Upvotes: 1

Views: 226

Answers (2)

CALUM Polwart
CALUM Polwart

Reputation: 537

library(dplyr)
library(data.table)

mydf <- structure(list(times = c("22:55:00", "01:05:00", "21:00:00")), class = "data.frame", row.names = c(NA, 
-3L))

mydf %>%
  mutate(
    times = as.ITime(times),
    difference = case_when (
      times > as.ITime("20:00:00") ~ difftime(times, as.ITime("20:00:00")),
      TRUE ~ difftime(as.ITime("23:59:59"), as.ITime("19:59:59")) 
               + difftime(  times, as.ITime("00:00:01"))
    )
  )

Upvotes: 1

akrun
akrun

Reputation: 886928

We convert to period class with hms, create a condition to check whether the compared time value is greater than the 'times', then add 1 day and subtract or else just subtract

library(dplyr)
library(lubridate)
df %>% 
    mutate(times1 = hms(times), times2 = hms("20:00:00"), 
       new = as.numeric(case_when(times1 < times2 ~ 
      (times1 + hms("24:00:00") - times2), TRUE ~ times2- times1))/3600 ) %>%
   select(times, new)
#     times       new
#1 22:55:00 -2.916667
#2 01:05:00  5.083333
#3 21:00:00 -1.000000

Upvotes: 2

Related Questions