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"
Related
I have a dataset with a column where date and time is stored.
The data I have is:
03/17/2020 09:30:00 PM
I want to convert AM/PM to a 24hour format.
My attempt was using this:
as.POSIXct(df$Date, format="%d/%m/%Y %I:%M:%S %p", tz="UTC")
When I run this with the whole dataset, the majority of dates turns into "NA".
Why is this happening? I am really confused.
Using lubridate:
x <- "03/17/2020 09:30:00 PM"
lubridate::mdy_hms(x)
[1] "2020-03-17 21:30:00 UTC"
Using as.Posixct: note that you need the month / day convention, not the day/month:
as.POSIXct(x, format="%m/%d/%Y %I:%M:%S %p", tz = "UTC")
[1] "2020-03-17 21:30:00 UTC"
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 am struggling a bit with lubridate
I have a date series in the past in df$mydate variable as POSIXct. I want to take max(df$mydate) subtract it from now(), then subtract 2 more days from that time interval - i.e. make the interval 2 days shorter than the difference between the latest date of the series and today. The obtained time interval then should be added to all dates in df$mydate so that the dates block is brought forward to end 2 days in the past from today.
How can I do this with lubridate?
when I try to convert now() - max(df$mydate) to interval I get an empty interval. So I do not even get to step 2 - shortening the interval by 2 days and to step 3 - trying to then add this time length to dates I have.
The Idee with lubridate is to take care of all the transformation between intervals and dates for you so you don't need to think about it. This simple code does exactly that what you want.
library(lubridate)
my_date <-as.POSIXlt(paste0("2009-08-",1:10))
time_diff <- now() - max(my_date)
time_diff_short = time_diff - 2
my_date + time_diff_short
What I found was that you need my_date to be of the format POSIXlt
You can use difftime from base to get the time difference to now Sys.time() and subtract 2 days.
x <- x + (difftime(Sys.time(), max(x), units = "days") - 2)
x
#[1] "2020-09-11 10:32:20 CEST" "2020-09-12 10:32:20 CEST"
#[3] "2020-09-13 10:32:20 CEST" "2020-09-14 10:32:20 CEST"
Sys.time()
#[1] "2020-09-16 10:32:20 CEST"
Data:
(x <- seq(as.POSIXct("2000-01-01 12:00:00"), length.out = 4, by = "days"))
#[1] "2000-01-01 12:00:00 CET" "2000-01-02 12:00:00 CET"
#[3] "2000-01-03 12:00:00 CET" "2000-01-04 12:00:00 CET"
I have data provided in the form of a date telling the day (format "YYYY-MM-DD", e.g. "2015-03-11" and the hours of the day numbered (0-23).
What is the most convenient way to produce time objects of the form
"2015-03-11" and hour = 0 -> "2015-03-11 00:00"
"2015-03-11" and hour = 1 -> "2015-03-11 01:00"
"2015-03-11" and hour = 2 -> "2015-03-11 02:00"
I could use the Date function from Base or something from xts or timeDate.
Should be easy but I am sure someone out there knows it quickly.
EDIT: the data is provided in 2 columns, one for the date and one numerical.
You don't need an external package to do that.
If your data is in this format:
df=data.frame(date=c("2015-03-11","2015-03-11","2015-03-11"),hour=0:2)
just apply the following function:
format(as.POSIXct(df$date)+df$hour*60*60, format = "%Y-%m-%d %H:%M")
Suppose we have this input:
date <- c("2015-03-11", "2015-03-12")
hour <- 2:3
then try one of these:
1) chron
library(chron)
as.chron(date) + hour/24
giving:
[1] (03/11/15 02:00:00) (03/12/15 03:00:00)
2) POSIXct. This one only uses the base of R, no packages:
as.POSIXct(date) + 3600 * hour
giving, on my system:
[1] "2015-03-11 02:00:00 EDT" "2015-03-12 03:00:00 EDT"
If you wanted the result in the UTC time zone use:
as.POSIXct(date, tz = "UTC") + 3600 * hour
3) lubridate
library(lubridate)
ymd(date) + hours(hour)
giving:
[1] "2015-03-11 02:00:00 UTC" "2015-03-12 03:00:00 UTC"
If you want it in the current time zone then:
ymd(date, tz = "") + hours(hour)
Note that the chron solution gives a date/time class that does not use time zones eliminating the many problems that time zones can cause. The POSIXct and lubridate solutions give the date/time in a specific time zone as shown.
You could try
dtime <- with(df, as.POSIXct(sprintf('%s %02d', date, hour),
format = "%Y-%m-%d %H"))
and then use format as in the other posts
Or
library(lubridate)
ymd_h(with(df, sprintf('%s %02d', date, hour)))
Or slightly more compact
ymd_h(do.call(paste, df))
Try this. You can format it without seconds afterwards using format if you wish, though I think it is preferable to keep it in POSIXct class so you can manipulate it afterwords (adding removing days, seconds, etc.)
as.POSIXct(do.call(paste, df), format = "%Y-%m-%d %H")
## [1] "2015-03-11 00:00:00 IST" "2015-03-11 01:00:00 IST" "2015-03-11 02:00:00 IST"
Though, If you insist on your exact output, here's the solution with format
format(as.POSIXct(do.call(paste, df), format = "%Y-%m-%d %H"), "%Y-%m-%d %H:%M")
## [1] "2015-03-11 00:00" "2015-03-11 01:00" "2015-03-11 02:00"
Data
df <- structure(list(V1 = structure(c(1L, 1L, 1L), .Label = "2015-03-11", class = "factor"),
V2 = 0:2), .Names = c("V1", "V2"), class = "data.frame", row.names = c(NA,
-3L))
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.