Search code examples
rtimedurationlubridatedifftime

R as.difftime() issue for times longer than 1 day


I need to convert time intervals in the format %H:%M:%S (class = factor) to class = difftime. I am currently using as.difftime() to do this, but it returns NA when the hour value is > 23.

TimeElapsed_raw = as.factor(c("03:59:59", "21:00:00", "01:03:46", "44:00:00", "24:59:59"))
TimeElapsed = as.difftime(as.character(TimeElapsed_raw), format = "%H:%M:%S")
TimeElapsed

Time differences in hours
[1]  3.999722 21.000000  1.062778        NA        NA

I have the same problem whether or not I include the format statement in as.difftime():

as.difftime("65:01:17")
Time difference of NA secs

But this works:

as.difftime(65.1, units = "hours")
Time difference of 65.1 hours

I've also tried using the lubridate as.duration() function, but the values it calculates seem nonsensical.

as.duration(TimeElapsed_raw)
[1] "2s" "3s" "1s" "5s" "4s"

Any help would be appreciated!


Solution

  • You could first change the format of your data to xH xM xS which is understood by the duration function in lubridate:

    x=gsub("(^\\d{2}):(\\d{2}):(\\d{2})$","\\1H \\2M \\3S",as.character(TimeElapsed_raw))
    [1] "03H 59M 59S" "21H 00M 00S" "01H 03M 46S" "44H 00M 00S" "24H 59M 59S"
    

    And then apply duration:

    duration(x)
    [1] "14399s (~4 hours)"     "75661s (~21.02 hours)" "3826s (~1.06 hours)"  
    [4] "158461s (~1.83 days)"  "89999s (~1.04 days)"  
    

    Otherwise, using as.difftime, you could first split your data into hours, minutes and seconds and feed each one seperately to as.difftime:

    v=lapply(strsplit(TimeElapsed_raw,":"),function(x) {as.difftime(as.numeric(x[1]),units="hours")+as.difftime(as.numeric(x[2]),units="mins")+as.difftime(as.numeric(x[3]),units="secs")})
    
    [[1]]
    Time difference of 14399 secs
    
    [[2]]
    Time difference of 75600 secs
    
    [[3]]
    Time difference of 3826 secs
    
    [[4]]
    Time difference of 158400 secs
    
    [[5]]
    Time difference of 89999 secs
    

    If you want to convert the list to a vector, make sure to reconvert it to difftime afterwards as unlist loses the class.

    v=as.difftime(unlist(v),unit="secs")