A blog by Jonas Kristoffer Lindeløv

# Fast rounding of datetime in R

Working with `POSIXct` objects in R can be slow. To floor a million timestamps down to the nearest quarter-of-hour takes ~7 seconds on my laptop using the usual functions: `lubridate::floor_date()` and `clock::date_floor()`.

Here is a base R function that achieves the same result in 10 ms:

``````round_time = function(x, precision, method = round) {
if ("POSIXct" %in% class(x) == FALSE)
stop("x must be POSIXct")

tz = attributes(x)\$tzone
secs_rounded = method(as.numeric(x) / precision) * precision
as.POSIXct(secs_rounded, tz = tz, origin = "1970-01-01")
}``````

You can use it like this:

``````# A million timestamps:
times = Sys.time() + rnorm(10^6, sd = 10^8)

# Round down to nearest quarter-of-hour
round_time(times, precision = 60*15, method = floor)

# Round up to nearest 5 seconds
round_time(times, precision = 5, method = ceiling)

# Round to the nearest minute (method = round is default):
round_time(times, precision = 60)``````

Let’s benchmark it against lubridate and clock to verify the ~700x speedup:

``````times = Sys.time() + rnorm(10^6, sd = 10^8)
bench::mark(round_time(times, precision = 60*15, method = floor))
bench::mark(clock::date_floor(times, precision = "minute", n = 15))
bench::mark(lubridate::floor_date(times, unit = "15 minutes"))``````