Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Round a POSIX date (POSIXct) with base R functionality

I'm currently playing around a lot with dates and times for a package I'm building.

Stumbling across this post reminded me again that it's generally not a bad idea to check out if something can be done with basic R features before turning to contrib packages.

Thus, is it possible to round a date of class POSIXct with base R functionality?

I checked

methods(round)

which "only" gave me

[1] round.Date      round.timeDate*

   Non-visible functions are asterisked

This is what I'd like to do (Pseudo Code)

x <- as.POSIXct(Sys.time())
[1] "2012-07-04 10:33:55 CEST"

round(x, atom="minute")
[1] "2012-07-04 10:34:00 CEST"

round(x, atom="hour")
[1] "2012-07-04 11:00:00 CEST"

round(x, atom="day")
[1] "2012-07-04 CEST"

I know this can be done with timeDate, lubridate etc., but I'd like to keep package dependencies down. So before going ahead and checking out the source code of the respective packages, I thought I'd ask if someone has already done something like this.

like image 330
Rappster Avatar asked Jul 04 '12 08:07

Rappster


People also ask

What is Posix date format in R?

POSIXct stores date and time in seconds with the number of seconds beginning at 1 January 1970. Negative numbers are used to store dates prior to 1970. Thus, the POSIXct format stores each date and time a single value in units of seconds. Storing the data this way, optimizes use in data.

How do I extract a date from POSIXct in R?

To get the year from a date in R you can use the functions as. POSIXct() and format() . For example, here's how to extract the year from a date: 1) date <- as. POSIXct("02/03/2014 10:41:00", format = "%m/%d/%Y %H:%M:%S) , and 2) format(date, format="%Y") .

What is the difference between POSIXlt and POSIXct?

There are two POSIX date/time classes, which differ in the way that the values are stored internally. The POSIXct class stores date/time values as the number of seconds since January 1, 1970, while the POSIXlt class stores them as a list with elements for second, minute, hour, day, month, and year, among others.

What is POSIXt?

A virtual class "POSIXt" exists from which both of the classes inherit: it is used to allow operations such as subtraction to mix the two classes. Components wday and yday of "POSIXlt" are for information, and are not used in the conversion to calendar time.


3 Answers

base has round.POSIXt to do this. Not sure why it doesn't come up with methods.

x <- as.POSIXct(Sys.time())
x
[1] "2012-07-04 10:01:08 BST"
round(x,"mins")
[1] "2012-07-04 10:01:00 BST"
round(x,"hours")
[1] "2012-07-04 10:00:00 BST"
round(x,"days")
[1] "2012-07-04"
like image 98
James Avatar answered Oct 20 '22 00:10

James


On this theme with lubridate, also look into the ceiling_date() and floor_date() functions:

x <- as.POSIXct("2009-08-03 12:01:59.23")
ceiling_date(x, "second")
# "2009-08-03 12:02:00 CDT"
ceiling_date(x, "hour")
# "2009-08-03 13:00:00 CDT"
ceiling_date(x, "day")
# "2009-08-04 CDT"
ceiling_date(x, "week")
# "2009-08-09 CDT"
ceiling_date(x, "month")
# "2009-09-01 CDT"
like image 27
nzcoops Avatar answered Oct 20 '22 02:10

nzcoops


If you don't want to call external libraries and want to keep POSIXct as I do this is one idea (inspired by this question): use strptime and paste a fake month and day. It should be possible to do it more straight forward, as said in this comment

"For strptime the input string need not specify the date completely: it is assumed that unspecified seconds, minutes or hours are zero, and an unspecified year, month or day is the current one."

Thus it seems that you have to use strftime to output a truncated string, paste the missing part and convert again in POSIXct.

This is how an update answer could look:

x <- as.POSIXct(Sys.time())
x
[1] "2018-12-27 10:58:51 CET"
round(x,"mins")
[1] "2018-12-27 10:59:00 CET"
round(x,"hours")
[1] "2018-12-27 11:00:00 CET"
round(x,"days")
[1] "2018-12-27 CET"
as.POSIXct(paste0(strftime(x,format="%Y-%m"),"-01"))     #trunc by month
[1] "2018-12-01 CET"
as.POSIXct(paste0(strftime(x,format="%Y"),"-01-01"))     #trunc by year
[1] "2018-01-01 CET"
like image 1
Simon C. Avatar answered Oct 20 '22 00:10

Simon C.