How to add/subtract time from a POSIXlt time while keeping its class in R?

sunt picture sunt · Jan 13, 2012 · Viewed 42.1k times · Source

I am manipulating some POSIXlt DateTime objects. For example I would like to add an hour:

my.lt = as.POSIXlt("2010-01-09 22:00:00")
new.lt = my.lt + 3600
new.lt
# [1] "2010-01-09 23:00:00 EST"
class(new.lt)
# [1] "POSIXct" "POSIXt" 

The thing is I want new.lt to be a POSIXlt object. I know I could use as.POSIXlt to convert it back to POSIXlt, but is there a more elegant and efficient way to achieve this?

Answer

IRTFM picture IRTFM · Jan 13, 2012

POSIXct-classed objects are internally a numeric value that allows numeric calculations. POSIXlt-objects are internally lists. Unfortunately for your desires, Ops.POSIXt (which is what is called when you use "+") coerces to POSIXct with this code:

if (inherits(e1, "POSIXlt") || is.character(e1)) 
        e1 <- as.POSIXct(e1)

Fortunately, if you just want to and an hour there is a handy alternative to adding 3600. Instead use the list structure and add 1 to the hour element:

> my.lt$hour <- my.lt$hour +1
> my.lt
[1] "2010-01-09 23:00:00"

This approach is very handy when you want to avoid thorny questions about DST changes, at least if you want adding days to give you the same time-of-day.

Edit (adding @sunt's code demonstrating that Ops.POSIXlt is careful with time "overflow".))

my.lt = as.POSIXlt("2010-01-09 23:05:00") 
my.lt$hour=my.lt$hour+1 
my.lt
# [1] "2010-01-10 00:05:00"