taking time difference from time in different format in R - r

I have a data.table dt which have many records .
It have two columns datetime1, with value as "2017-04-19 09:54:00" of class POSIXct
another column have time values like "7.97" of class numeric. It is for the same date.
I want to calculate a difference in the time in minutes. how can I do it in R

Try this
time1 <- as.POSIXct('2017-04-19 09:54:00')
time2 <- as.POSIXct('2017-04-19 00:00:00') + 3600*7.97
60*as.numeric(time1 - time2)

You can use functions of lubridate to extract hour, minute, and second of the POSIXct and then calculate the difference.
library(lubridate)
x = as.POSIXct("2017-04-19 09:54:00", tz = "UTC")
hour(x) * 60 + minute(x) + second(x)/60 - 7.97 * 60
#[1] 115.8

Related

Calculation of time intervals using 'lubridate'

For statistical reasons, I would like to calculate the following:
date2 - date1 +1(day) ; in month.
For the above equation, this shall mean 1 day if date2 == date1.
For data, time data is only available for Y,M,D (no HH,MM).
The date below is available for demo.
date <- as.POSIXct("2009-03-08")
date2 <- as.POSIXct("2009-03-09")
I would like to get
( (date %--% date2)+1 )/ months(1)
(But this doesn’t work)
( (date %--% date2)+1 )/ days(1)
gives me 2 (days).
Now, I would like to calculate this value to month.
How can I achieve this?
Or rather, can I go straightforward,
like below equation?
( (date %--% date2)+1 )/ months(1)
First edition (Deprecated)
date %--% date2 is a <Interval>. You cannot add a numeric value to it. Instead, you need to convert it into a <Period>.
(as.period(date %--% date2) + days(1)) / months(1)
# [1] 0.06570842
Update
The above method is not precise because it cannot take months into account. The ideal output should be
(1 + 1) / 31
# [1] 0.06451613
becasue March has 31 days. The following way is able to consider the differences of days between different months.
(date %--% (date2 + days(1))) / months(1)
# [1] 0.06451613
For comparison, we change the dates to February and see the output:
date <- as.POSIXct("2009-02-08")
date2 <- as.POSIXct("2009-02-09")
(date %--% (date2 + days(1))) / months(1)
# [1] 0.07142857
which is equal to (1 + 1)/28.
The difftime command in base R subtracts one date from another. Unfortunately, it does not have the option to return the output in months; however, if we choose days, we can manually convert it.
Base
date1 <- as.POSIXct("2009-03-08")
date2 <- as.POSIXct("2009-03-09")
(1 + as.numeric(difftime(time1 = date2,time2 = date1,units = "days")))/30.4375
lubridate
library(lubridate)
date1 <- ymd("2009-03-08")
date2 <- ymd("2009-03-09")
(1 + as.numeric(date2 - date1))/30.4375
Output
[1] 0.06570842
Please try to divide the 2 dates by 30.4375 which is obtained from 365.25/12
Code
data.frame(date1=date, date2=date2) %>% mutate(date1=as.Date(date1),
date2=as.Date(date2),
diff=(date1-date2)/30.4375)

how to calculate time interval and divide it by integer in r?

i have time string as "08:00","06:00"
and i wanna calculate difference between them
and divide it by 15 mins.
then results should be 8 in integer
i don't how to code in R
anybody can help me ?
Something like this using difftime?
difftime(
as.POSIXct("08:00", format = "%H:%M"),
as.POSIXct("06:00", format = "%H:%M"),
units = "mins") / 15
#Time difference of 8 mins
Or to convert to numeric
as.numeric(
difftime(as.POSIXct("08:00", format = "%H:%M"),
as.POSIXct("06:00", format = "%H:%M"),
units = "mins") / 15)
#[1] 8
It would be easy with lubridate, where we convert the strings in hm format and divide by 15 minutes.
library(lubridate)
(hm(a) - hm(b))/minutes(15)
#[1] 8
data
a <- "08:00"
b <- "06:00"

Converting a number into time (0,5 of an hour = 00:30:00)

I am trying to convert a number into time format.
For example:
I calculate how long has to be charged an electric car at the charging station of 11 kWh.
Energy demand - 2,8 kWh
Charging time = 2,8 kWh/11 kWh = 0,257 h
0,257 h = 15 min 25 sec. = 00:15:25
How can I convert 0,257 h into 00:15:25 in R?
Based on the example, we will assume that the input is less than 24 (but if that is not the case these could be modified to handle that depending on the definition of what such an input should produce).
1) chron::times Use chron times like this. times measures times in fractions of a day so divide the hours (.257) by 24 to give the fraction of a day that it represents.
library(chron)
times(.257 / 24)
## [1] 00:15:25
This gives a chron "times" class object. If x is such an object use format(x) to convert it to a character string, if desired.
2) POSIXct This uses no packages although it is longer. It returns the time as a character string. POSIXct measures time in seconds and so multiply the hours (.257) by 3600 as there are 3600 seconds in an hour.
format(as.POSIXct("1970-01-01") + 3600 * .257, "%H:%M:%S")
## [1] "00:15:25"
2a) This variation would also work. It is longer but it involves no conversion factors. It returns a character string.
format(as.POSIXct("1970-01-01") + as.difftime(.257, units = "hours"), "%H:%M:%S")
## [1] "00:15:25"
Updates: Added (2). Also added (2a) and improved (2).
The answer by #GGrothendieck seems to be the way to go here. But if you had to do this in base R, you could just compute the hour, minute, and second components and build the time string manually:
x <- 2.257 # number of hours
total <- round(x*60*60, digits=0) # the total number of seconds
hours <- trunc(total / (60*60))
minutes <- trunc((x - hours) * 60)
seconds <- total %% 60
ts <- paste0(formatC(hours, width=2, flag="0"), ":",
formatC(minutes, width=2, flag="0"), ":",
formatC(seconds, width=2, flag="0"))
ts
[1] "02:15:25"
Demo
The tidyverse solution would use the hms package:
hms::hms(0.257 * 60^2)
#> 00:15:25.2
Gives you an object of classes hms and difftime. If you want a string:
format(hms::hms(0.257 * 60^2))
#> [1] "00:15:25.2"

R: Calculate time intervals

If I have a vector of dates and hours such as...
c("2016-03-15 13","2016-03-16 23","2016-03-17 06","2016-03-18 15","2016-03-19 08","2016-03-20 21")
Can I find the number of hours that pass between each timestamp? I looked into difftime but it requires 2 vectors.
We can do this after converting to 'DateTime' class using lubridate, then get the difference in 'hour' between adjacent elements using difftime by passing two vectors after removing the last and first observation in the vector
library(lubridate)
v2 <- ymd_h(v1)
Or a base R option is as.POSIXct
v2 <- as.POSIXct(v1, format = "%Y-%m-%d %H")
and then do the difftime
difftime(v2[-length(v2)], v2[-1], unit = "hour")
data
v1 <- c("2016-03-15 13","2016-03-16 23","2016-03-17 06",
"2016-03-18 15","2016-03-19 08","2016-03-20 21")
You can do this by using strptime() function.
Try something like this.
data <- c("2016-03-15 13","2016-03-16 23","2016-03-17 06","2016-03-18 15","2016-03-19 08","2016-03-20 21")
datevec <- strptime(data,"%Y-%m-%d %H")
difftime(datevec[-length(datevec)],datevec[-1],units="hours")
Here is the output.
> difftime(datevec[-length(datevec)],datevec[-1],units="hours")
Time differences in hours
[1] -34 -7 -33 -17 -37

Create vector of non-weekend time intervals for part of a day in R

I have a raw dataset of observations taken at 5 minute intervals between 6am and 9pm during weekdays only. These do not come with date-time information for plotting etc so I am attempting to create a vector of date-times to add to this to my data. ie this:
X425 X432 X448
1 0.07994814 0.1513559 0.1293103
2 0.08102852 0.1436480 0.1259074
to this
X425 X432 X448
2010-05-24 06:00 0.07994814 0.1513559 0.1293103
2010-05-24 06:05 0.08102852 0.1436480 0.1259074
I have gone about this as follows:
# using lubridate and xts
library(xts)
library(lubridate)
# sequence of 5 min intervals from 06:00 to 21:00
sttime <- hms("06:00:00")
intervals <- sttime + c(0:180) * minutes(5)
# sequence of days from 2010-05-24 to 2010-11-05
dayseq <- timeBasedSeq("2010-05-24/2010-11-05/d")
# add intervals to dayseq
dayPlusTime <- function(days, times) {
dd <- NULL
for (i in 1:2) {
dd <- c(dd,(days[i] + times))}
return(dd)
}
obstime <- dayPlusTime(dayseq, intervals)`
But obstime is coming out as a list. days[1] + times works so I guess it's something to do with the way the POSIXct objects are concatenated together to make dd but i can't figure out what am I doing wrong otr where to go next.
Any help appreciated
A base alternative:
# create some dummy dates
dates <- Sys.Date() + 0:14
# select non-weekend days
wd <- dates[as.integer(format(dates, format = "%u")) %in% 1:5]
# create times from 06:00 to 21:00 by 5 min interval
times <- format(seq(from = as.POSIXct("2015-02-18 06:00"),
to = as.POSIXct("2015-02-18 21:00"),
by = "5 min"),
format = "%H:%M")
# create all date-time combinations, paste, convert to as.POSIXct and sort
wd_times <- sort(as.POSIXct(do.call(paste, expand.grid(wd, times))))
One of the issues is that your interval vector does not change the hour when the minutes go over 60.
Here is one way you could do this:
#create the interval vector
intervals<-c()
for(p in 6:20){
for(j in seq(0,55,by=5)){
intervals<-c(intervals,paste(p,j,sep=":"))
}
}
intervals<-c(intervals,"21:0")
#get the days
dayseq <- timeBasedSeq("2010-05-24/2010-11-05/d")
#concatenate everything and format to POSIXct at the end
obstime<-strptime(unlist(lapply(dayseq,function(x){paste(x,intervals)})),format="%Y-%m-%d %H:%M", tz="GMT")

Resources