Search code examples
rdurationdifftime

How to convert colon notation duration time if we have more than 60 minutes


I am stuck with something simple: I have vector of minutes and seconds like, e.g., myvec=c("10:56","2:32","0:00","0:00","62:59","60:40","46:23"). Here the number before the : notes the minutes and after the colon we have the seconds.

I tried

difftime(myvec,format='%M:%S')
Error in difftime(myvec, format = "%M:%S") : 
  unused argument (format = "%M:%S")

however my problem seems to be that some minutes values are bigger than 60. I am a bit startled that I can't think of any straightforward solution. Maybe I just misunderstood the difftime documentation. Sorry if this creates a duplicate.

EDIT:

Since some people asked:

as.difftime(myvec,format='%M:%S',units='mins')
10.933333  2.533333  0.000000  0.000000        NA        NA 46.383333

Instead of the two NAs I want the command to return something like 62.9999 60.6666. At this point I am just curious whether there is any solution without using regex.


Solution

  • Here are some alternatives. Except for (2) they use no packages.

    1) sub Extract the numbers, convert to numeric and compute the seconds.

    60 * as.numeric(sub(":.*", "", myvec)) + as.numeric(sub(".*:", "", myvec))
    ## [1]  656  152    0    0 3779 3640 2783
    

    2) strapply We could also use strapply in gsubfn:

    library(gsubfn)
    strapply(myvec, "(.+):(.+)", ~ 60 * as.numeric(min) + as.numeric(sec), simplify = TRUE)
    ## [1]  656  152    0    0 3779 3640 2783
    

    3) scan Another solution can be based on scan and matrix multiplication:

    c(c(60, 1) %*% matrix(scan(text = myvec, sep = ":", quiet = TRUE), 2))
    ## [1]  656  152    0    0 3779 3640 2783
    

    4) eval eval has a bad reputation but if you don't mind using it then it is the shortest of the solutions here.

    sapply(parse(text = paste0("60*", sub(":", "+", myvec))), eval)
    ## [1]  656  152    0    0 3779 3640 2783