Julien Vidal
Julien Vidal

Reputation: 33

How to add hours with lubridate without specific dates, and not over 24h?

I'm trying to use lubridate as a base for optimizing staff schedules. How can I write my dataframe for shifts and working hours without having to use particular dates in the calendar? (Yes I'm just starting, and already running into simple problems, I'm new to R...)

I wrote manually some of the information, but I need to be able to compute on a 24h day basis, so I tried to compute the working hours just to be sure.

shift <- c("week", "evening", "weeknight", "weekend", "weekendnight")
start <- c(hms::as.hms(27000), hms::as.hms(43200), hms::as.hms(77400), hms::as.hms(28800), hms::as.hms(72000))
end <- c(hms::as.hms(64800), hms::as.hms(79200), hms::as.hms(29700), hms::as.hms(72000), hms::as.hms(28800))
hours <- c(hms::as.hms(37800), hms::as.hms(36000), hms::as.hms(38700), hms::as.hms(43200), hms::as.hms(43200))


shiftsDF <- data.frame(shift, start, end, hours) %>%
mutate(computedhours = hms::as.hms(end-start)) 

I expected the "computedhours" to be the same as the "hours" that I entered manually, until I understood it was just the sum of seconds, regardless of the day. How can I make R studio understand that I'm talking about days without having to use exact dates?

Upvotes: 3

Views: 1190

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 389145

A base R way using difftime is to add a day (86400 seconds) to end if start > end and use difftime to get output in "hours" as units.

with(shiftsDF, ifelse(start > end, 
        difftime(as.POSIXct(end) + 86400, as.POSIXct(start), units = "hours") ,
        difftime(end, start, units=  "hours")))

#[1] 10.50 10.00 10.75 12.00 12.00

This returns hours as ratio where 10.5 means 10 hours 30 minutes, 10.75 means 10 hours 45 minutes and so on.

data

shiftsDF <- data.frame(shift, start, end, hours)

Upvotes: 0

A. Suliman
A. Suliman

Reputation: 13135

Using dplyr::if_else we can do

library(lubridate)
library(dplyr)
data.frame(shift, start, end, hours) %>%
    mutate(computedhours = if_else(end < start, 
                                   hms::as.hms(dmy_hms(paste('02/01/2019',end)) - dmy_hms(paste('01/01/2019',start))),
                                   hms::as.hms(end-start)))

Upvotes: 1

Related Questions