How do I add / subtract time from POSIXlt while keeping my class in R?

I am manipulating some DateTime objects POSIXlt

. 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" 

      

I want to new.lt

be an object POSIXlt

. 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?

+13


source to share


4 answers


Short answer: No

Long answer:



Objects

POSIXct

and POSIXlt

are two concrete types of a more general class POSIXt

(not in the sense of object-oriented inheritance, but in the sense of a quasi-object oriented implementation). The code switches freely between them. When you add an object POSIXlt

, the actual function used +.POSIXt

, not the one for POSIXlt

. Inside this function, the argument is converted to POSIXct

and then processed (appended).

Also, POSIXct

it is the number of seconds since a specific date and time. POSIXlt

- a list of date details (seconds, minutes, hours, day of month, month, year, day of the week, day of the year, DST info), so adding to this directly doesn't make sense. Converting it to a few seconds ( POSIXct

) and adding to it makes sense.

+12


source


POSIXct

-classified objects are internally a numeric value that allows numeric calculations. POSIXlt

-objects are internal lists. Unfortunately for your desires Ops.POSIXt

(this is what gets called when "+" is used) coercive POSIXct with this code:

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

      

Luckily, if you just want an hour, there is a convenient alternative to adding 3600. Use a list structure instead and add element 1 to the hour element:

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

      



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

Edit (adding @sunt's code demonstrating being Ops.POSIXlt

careful about 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"

      

+14


source


It might not be significantly more elegant, but

seq.POSIXt( from=Sys.time(), by="1 hour", length.out=2 )[2]

      

IMHO more clearly than

Sys.time()+3600;  # 60 minutes * 60 seconds

      

because the doc code itself indicates that you are going to "POSIX" "seq" uquance "for 1 hour", but that's a matter of taste. Works well on POSIXlt, but note that it returns POSIXct anyway. Also works for "days". See the help (seq.POSIXt) for details on how it handles months, daylight savings time, etc.

+7


source


?POSIXlt

tells you that:

Any conversion that needs to go between the two time classes requires a time zone: a conversion from "POSIXlt" to "POSIXct" will check the time in the selected time zone.

So i think 3600 is not an object POSIXlt

, there is an automatic conversion.

I would stick with a simple one:

new.lt = as.POSIXlt(my.lt + 3600)
class(new.lt)
[1] "POSIXlt" "POSIXt"

      

It's not much of a hassle to add time as.POSIXlt

before your surgery.

+5


source







All Articles