user6678274
user6678274

Reputation: 53

How to convert times over 24:00:00 in R

In R I have this data.frame

24:43:30 23:16:02 14:05:44 11:44:30 ...

Note that some of the times are over 24:00:00 ! In fact all my times are within 02:00:00 to 25:59:59.

I want to subtract all entries in my dataset data with 2 hours. This way I get a regular data-set. How can I do this?

I tried this

strptime(data, format="%H:%M:%S") - 2*60*60

and this work for all entries below 23:59:59. For all entries above I simply get NA since the strptime command produce NA to all entries above 23:59:59.

Upvotes: 1

Views: 1209

Answers (2)

RHertel
RHertel

Reputation: 23788

Although the answer by @amrrs solves the main problem, the formatting could remain an issue because hms() does not provide a uniform output. This is best shown with an example:

library(lubridate)
hms("01:23:45")
#[1] "1H 23M 45S"
hms("00:23:45")
#[1] "23M 45S"
hms("00:00:45")
#[1] "45S"

Depending on the time passed to hms() the output may or may not contain an entry for the hours and for the minutes. Moreover leading zeros are omitted in single-digit values of hours, minutes and seconds. This can result pretty much in a formatting nightmare if one tries to put that data into a common form.

To resolve this difficulty one could first convert the time into a duration with lubridate's as.duration() function. Then, the duration in seconds can be transformed into a POSIXct object from which the hours, minutes, and seconds can be extracted easily with format():

times <- c("24:43:30", "23:16:02", "14:05:44", "11:44:30", "02:00:12")
shifted_times <- hms(times) - hms("02:00:00")
format(.POSIXct(as.duration(shifted_times),tz="GMT"), "%H:%M:%S")
#[1] "22:43:30" "21:16:02" "12:05:44" "09:44:30" "00:00:12"

The last entry "02:00:12" would have caused difficulties if shifted_times had been passed to strptime().

Upvotes: 3

amrrs
amrrs

Reputation: 6325

Using lubridate package can make the job easier!

> library(lubridate)
> t <- '24:43:30'
> hms(t) - hms('2:0:0')
[1] "22H 43M 30S"

Update:

Converting the date back to text!

> substr(strptime(hms(t) - hms('2:0:0'),format='%HH %MM %SS'),12,20)
[1] "22:43:30"

Adding @RHertel's update:

format(strptime(hms(t) - hms('2:0:0'),format='%HH %MM %SS'),format='%H:%M:%S')

Better way of formating the lubridate object:

s <- hms('02:23:58) - hms('2:0:0')
paste(hour(s),minute(s),second(s),sep=":")
"0:23:58"

Upvotes: 4

Related Questions