Hi I have a character vector (rr) that is several million in length, and it represents time and date stamps in the format %Y-%m-%d %H:%M:%S recorded in Australia/Sydney.
How do get a POSIXct object (quickly) that represents this.
I have found fastPOSIXct in the fasttime package, but for this to be accurate, it requires the original character string to be in GMT/UTC, (which mine is not) and then converted back into the correct timezone using the tz arguement...
> head(rr)
[1] "2009-05-01 10:01:00" "2009-05-01 10:02:00" "2009-05-01 10:03:00" "2009-05-01 10:04:00"
[5] "2009-05-01 10:05:00" "2009-05-01 10:06:00"
> as.POSIXct(head(rr),tz="Australia/Sydney")
[1] "2009-05-01 10:01:00 EST" "2009-05-01 10:02:00 EST" "2009-05-01 10:03:00 EST"
[4] "2009-05-01 10:04:00 EST" "2009-05-01 10:05:00 EST" "2009-05-01 10:06:00 EST"
The above line takes ages if doing it on the full set of data...so any speed improvements would be appreciated. Thanks.
Inspired by Dirk's answer to this qn, I made this wrapper for handling a whole bunch of dates across the year:
fastPOSIXct_generic <- function(x, mytz = "America/New_York")
{
# Caution, read: ?DateTimeClasses
stopifnot(is.character(x))
times_UTC <- fastPOSIXct(x, tz='UTC')
num_times <- as.numeric(times_UTC)
t1 <- as.POSIXct(x[1], tz = mytz)
t2 <- as.POSIXct(x[1], tz = "UTC")
offset <- as.numeric(difftime(t1, t2, units = "secs"))
daylightoffset <- as.POSIXlt(t1)$isdst
# For this first 'time' in t1 and t2, remove possible impact of losing one hour by setting clocks one hour forward during summer months:
offset <- offset + daylightoffset * 3600
num_times <- num_times + offset
new_num_times <- as.POSIXct(num_times, tz = mytz, origin = '1970-01-01')
new_num_times2 <- new_num_times - as.POSIXlt(new_num_times)$isdst * 3600
return(new_num_times2)
}
# Test Sydney time
mm <- as.POSIXct(c("2015-03-15 15:00:00", "2015-4-10 15:00:00", "2014-10-01 15:00:00", "2015-10-15 15:00:00"), tz = "Australia/Sydney")
# "2015-03-15 15:00:00 AEDT" "2015-04-10 15:00:00 AEST" "2014-10-01 15:00:00 AEST" "2015-10-15 15:00:00 AEDT"
aus_stamps <- as.character(mm)
aus_back <- fastPOSIXct_generic(x = aus_stamps, mytz = "Australia/Sydney")
#"2015-03-15 15:00:00 AEDT" "2015-04-10 15:00:00 AEST" "2014-10-01 15:00:00 AEST" "2015-10-15 15:00:00 AEDT"
identical(mm, aus_back)
# TRUE
My use cases are nearly always UTC to America/New_York, where so far it has seemed to work fine. I don't know whether it works correctly for other time zones; just the cases where dst has time go forward an hour.
Here is one approach:
i) Lie to fasttime() and pretend the data was UTC, use to parse the data into a vector x
ii) Compute an offset to UTC using your first data point:
R> d1 <- "2009-05-01 10:01:01" ## or use `head(rr,1)`
R> t1 <- as.POSIXct(d1,tz="Australia/Sydney")
R> t2 <- as.POSIXct(d1,tz="UTC")
R> offset <- as.numeric(difftime(t2, t1, units="secs"))
R> offset
[1] 36000
iii) Apply the offset value to your data -- that is a quick addition as POSIXct really is a numeric type with (fractional) seconds (since epoch) as its unit.
Related
I have datetime object and I want to change all times to 2PM and keep the dates same.
I used floor_date to get the start of the corresponding date and then added period of 14 hours to get 2PM.
Sometime, result shows only the date and no time. Sometimes it shows both date and time.
Is there another approach to do this
library(lubridate)
t1 <- floor_date(Sys.time(), unit = "day") + hours(14)
t2 <- floor_date(ymd_hms("2021-08-25 10:36:00"), unit = "day") + hours(14)
You can replace the time component with the hour. Here is a function to do that.
change_time_to_x <- function(time, x) {
as.POSIXct(sub('\\s.*', x, time), tz = 'UTC')
}
input <- lubridate::ymd_hms(Sys.time(), "2021-08-25 10:36:00", "2012-12-31 00:00:00")
change_time_to_x(input, '14:00:00')
#[1] "2021-08-26 14:00:00 UTC" "2021-08-25 14:00:00 UTC" "2012-12-31 14:00:00 UTC"
I have data value
dput(a)
"1/3/2019 15:59"
I need to round the time to to the next hour. I need this date to be "1/3/2019 16:00"?
How can I do this?
We can use lubridate dmy_hm to convert to datetime object and then use ceiling_date to convert it to next hour.
library(lubridate)
ceiling_date(dmy_hm("1/3/2019 15:59"), "hour")
#[1] "2019-03-01 16:00:00 UTC"
Use round.POSIXt. No packages are used.
x <- as.POSIXct("1/3/2019 15:59", format = "%m/%d/%Y %H:%M")
round(x + 3600/2 - !(as.numeric(x) %% 3600), "hours")
## [1] "2019-01-03 16:00:00 EST"
This question already has answers here:
Convert date-time string to class Date
(4 answers)
Closed 3 years ago.
I have date&time stamp as a character variable
"2018-12-13 11:00:01 EST" "2018-10-23 22:00:01 EDT" "2018-11-03 14:15:00 EDT" "2018-10-04 19:30:00 EDT" "2018-11-10 17:15:31 EST" "2018-10-05 13:30:00 EDT"
How can I strip the time from this character vector?
PS: Can someone please help. I have tried using strptime but I am getting NA values as a result
It's a bit unclear whether you want the date or time but if you want the date then as.Date ignores any junk after the date so:
x <- c("2018-12-13 11:00:01 EST", "2018-10-23 22:00:01 EDT")
as.Date(x)
## [1] "2018-12-13" "2018-10-23"
would be sufficient to get a Date vector from the input vector x. No packages are used.
If you want the time then:
read.table(text = x, as.is = TRUE)[[2]]
## [1] "11:00:01" "22:00:01"
If you want a data frame with each part in a separate column then:
read.table(text = x, as.is = TRUE, col.names = c("date", "time", "tz"))
## date time tz
## 1 2018-12-13 11:00:01 EST
## 2 2018-10-23 22:00:01 EDT
I think the OP wants to extract the time from date-time variable (going by the title of the question).
x <- "2018-12-13 11:00:01 EST"
as.character(strptime(x, "%Y-%m-%d %H:%M:%S"), "%H:%M:%S")
[1] "11:00:01"
Another option:
library(lubridate)
format(ymd_hms(x, tz = "EST"), "%H:%M:%S")
[1] "11:00:01"
The package lubridate makes everything like this easy:
library(lubridate)
x <- "2018-12-13 11:00:01 EST"
as_date(ymd_hms(x))
You can use the as.Date function and specify the format
> as.Date("2018-12-13 11:00:01 EST", format="%Y-%m-%d")
[1] "2018-12-13"
If all values are in a vector:
x = c("2018-12-13 11:00:01 EST", "2018-10-23 22:00:01 EDT",
"2018-11-03 14:15:00 EDT", "2018-10-04 19:30:00 EDT",
"2018-11-10 17:15:31 EST", "2018-10-05 13:30:00 EDT")
> as.Date(x, format="%Y-%m-%d")
[1] "2018-12-13" "2018-10-23" "2018-11-03" "2018-10-04" "2018-11-10"
[6] "2018-10-05"
i have a time series Data with 10 Minutes difference when i try to convert to date and time type using `df$Time1 <- dmy_hm(df$Time, tz="Asia/Calcutta")
it returns NA at 24 o Clock time interval as you can see i have tried with df$Time1 <- dmy_hm(df$Time, tz="Asia/Calcutta")and df$Time1 = as.POSIXct(df$Time, format="%d-%m-%y %H:%M") Please do guide me on this i am clueless whats happening at 02-07-16 00:00
One option would be using parse_date_time from lubridate which can take multiple formats
library(lubridate)
parse_date_time(df$Time, c('dmy_HM', 'dmy'))
#[1] "2016-07-01 23:30:00 UTC" "2016-07-01 23:40:00 UTC"
#[3] "2016-07-01 23:50:00 UTC" "2016-07-02 00:00:00 UTC"
data
df <- data.frame(Time = c("01-07-16 23:30", "01-07-16 23:40", "01-07-16 23:50",
"02-07-16"))
I would like to add 1 hour to a POSIXct object, but it does not support '+'.
This command:
as.POSIXct("2012/06/30","GMT")
+ as.POSIXct(paste(event_hour, event_minute,0,":"), ,"%H:%M:$S")
returns this error:
Error in `+.POSIXt`(as.POSIXct("2012/06/30", "GMT"), as.POSIXct(paste(event_hour, :
binary '+' is not defined for "POSIXt" objects
How can I add a few hours to a POSIXct object ?
POSIXct objects are a measure of seconds from an origin, usually the UNIX epoch (1st Jan 1970). Just add the requisite number of seconds to the object:
x <- Sys.time()
x
[1] "2012-08-12 13:33:13 BST"
x + 3*60*60 # add 3 hours
[1] "2012-08-12 16:33:13 BST"
The lubridate package also implements this nicely with convenience functions hours, minutes, etc.
x = Sys.time()
library(lubridate)
x + hours(3) # add 3 hours
James and Gregor's answers are great, but they handle daylight saving differently. Here's an elaboration of them.
# Start with d1 set to 12AM on March 3rd, 2019 in U.S. Central time, two hours before daylight saving
d1 <- as.POSIXct("2019-03-10 00:00:00", tz = "America/Chicago")
print(d1) # "2019-03-10 CST"
# Daylight saving begins # 2AM. See how a sequence of hours works. (Basically it skips the time between 2AM and 3AM)
seq.POSIXt(from = d1, by = "hour", length.out = 4)
# "2019-03-10 00:00:00 CST" "2019-03-10 01:00:00 CST" "2019-03-10 03:00:00 CDT" "2019-03-10 04:00:00 CDT"
# Now let's add 24 hours to d1 by adding 86400 seconds to it.
d1 + 24*60*60 # "2019-03-11 01:00:00 CDT"
# Next we add 24 hours to d1 via lubridate seconds/hours/days
d1 + lubridate::seconds(24*60*60) # "2019-03-11 CDT" (i.e. 2019-03-11 00:00:00 CDT)
d1 + lubridate::hours(24) # "2019-03-11 CDT" (i.e. 2019-03-11 00:00:00 CDT)
d1 + lubridate::days(1) # "2019-03-11 CDT" (i.e. 2019-03-11 00:00:00 CDT)
So, either answer is correct depending on what you want. Of course, if you're using UTC or some other timezone that doesn't observe daylight saving, these two methods should be the same.