Как добавить / вычесть время из времени POSIXlt, сохраняя его класс в R? - PullRequest
16 голосов
/ 14 января 2012

Я манипулирую некоторыми POSIXlt объектами DateTime.Например, я хотел бы добавить час:

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" 

Дело в том, что я хочу, чтобы new.lt был POSIXlt объектом.Я знаю, что мог бы использовать as.POSIXlt, чтобы преобразовать его обратно в POSIXlt, но есть ли более элегантный и эффективный способ добиться этого?

Ответы [ 4 ]

15 голосов
/ 14 января 2012

POSIXct -классированные объекты внутренне являются числовыми значениями, которые допускают числовые вычисления.POSIXlt -объекты являются внутренне списками.К сожалению для ваших желаний, Ops.POSIXt (что называется, когда вы используете "+") приводит к POSIXct с этим кодом:

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

К счастью, если вы просто хотите, и час естьУдобная альтернатива добавлению 3600. Вместо этого используйте структуру списка и добавьте 1 к элементу часа:

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

Этот подход очень удобен, когда вы хотите избежать острых вопросов об изменениях летнего времени, по крайней мере, если вы хотите добавитьдней, чтобы дать вам одно и то же время суток.

Редактировать (добавив код @ sunt, демонстрирующий, что Ops.POSIXlt осторожен со «переполнением» времени.))

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"
12 голосов
/ 14 января 2012

Краткий ответ: Нет

Длинный ответ:

Объекты

POSIXct и POSIXlt являются двумя конкретными типами более общего класса POSIXt (не в строго объектно-ориентированном смысле наследования, а в квази-объектно-ориентированном смысле реализации). Код свободно переключается между ними. Когда вы добавляете к POSIXlt объекту, фактическая используемая функция равна +.POSIXt, а не специально для POSIXlt. Внутри этой функции аргумент преобразуется в POSIXct, а затем обрабатывается (добавляется в).

Кроме того, POSIXct - это количество секунд от определенной даты и времени. POSIXlt - это список частей даты (секунды, минуты, часы, день месяца, месяц, год, день недели, день года, информация о летнем времени), поэтому добавление к нему напрямую не имеет никакого смысла. Преобразование его в число секунд (POSIXct) и добавление к нему имеет смысл.

7 голосов
/ 18 апреля 2014

Это может быть не намного элегантнее, но

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

ИМХО является более информативным, чем

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

, потому что сам код документирует, что вы собираетесь использовать «POSIX»seq увеличивается на 1 час, но это дело вкуса.Отлично работает на POSIXlt, но учтите, что он возвращает POSIXct в любом случае.Также работает на «дни».См. Справку (seq.POSIXt) для получения подробной информации о том, как она обрабатывает месяцы, летнее время и т. Д.

5 голосов
/ 14 января 2012

?POSIXlt говорит вам, что:

Любое преобразование, которое необходимо выполнить между двумя классами даты и времени, требует часовой пояс: преобразование из "POSIXlt" в "POSIXct" будет проверять время ввыбранный часовой пояс.

Так что я думаю, что 3600 не является POSIXlt объектом, есть автоматическое преобразование.

Я бы придерживался простого:

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

Не так уж сложно добавить as.POSIXlt перед вашей временной операцией.

...