web-dev-qa-db-ja.com

クラスをRに保ちながらPOSIXlt時間に時間を加算/減算する方法は?

いくつかのPOSIXlt DateTimeオブジェクトを操作しています。たとえば、1時間追加したいとします。

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.ltPOSIXltオブジェクトにします。 as.POSIXlt変換してPOSIXltに戻しますが、これを実現するためのよりエレガントで効率的な方法はありますか?

16
sunt

短い答え:いいえ

長い答え:

POSIXctおよびPOSIXltオブジェクトは、より一般的なPOSIXtクラスの2つの特定のタイプです(厳密にオブジェクト指向の継承という意味ではなく、準オブジェクト指向の実装という意味で)。コードはこれらを自由に切り替えます。 POSIXltオブジェクトに追加する場合、実際に使用される関数は+.POSIXtPOSIXlt専用ではありません。この関数内では、引数はPOSIXctに変換されてから処理(追加)されます。

さらに、POSIXctは特定の日時からの秒数です。 POSIXltは日付部分(秒、分、時間、日、月、年、曜日、年、DST情報)のリストであるため、これに直接追加しても意味がありません。それを秒数(POSIXct)に変換し、それに追加することには意味があります。

12
Brian Diggs

POSIXct- classedオブジェクトは、内部的には数値計算を可能にする数値です。 POSIXlt- objectsは内部的にリストです。残念ながら、Ops.POSIXt( "+"を使用すると呼び出される)は、次のコードでPOSIXctに強制変換します。

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

幸いなことに、1時間だけしたい場合は、3600を追加する代わりに便利な方法があります。代わりに、リスト構造を使用して、時間要素に1を追加します。

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

この方法は、DSTの変更に関する厄介な質問を避けたい場合、少なくとも同じ時間帯に日数を追加したい場合に非常に便利です。

編集(@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"
16
42-

それほどエレガントではないかもしれませんが、

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

私見はより説明的です

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

コード自体が、「POSIX」「seq」の単位が「1時間ずつ」増加することを文書化しているためですが、それは好みの問題です。 POSIXltでは問題なく動作しますが、どちらの方法でもPOSIXctを返すことに注意してください。 「日」でも機能します。月や夏時間などの処理方法の詳細については、help(seq.POSIXt)を参照してください。

8
woodvi

?POSIXltは次のように説明しています。

2つの日時クラス間を移動する必要がある変換にはタイムゾーンが必要です。「POSIXlt」から「POSIXct」への変換では、選択したタイムゾーンの時刻が検証されます。

したがって、3600はPOSIXltオブジェクトではなく、自動変換があると思います。

私は単純に固執します:

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

時間操作の前にas.POSIXltを追加するのはそれほど面倒ではありません。

5
Pierre Lapointe