Come aggiungere/sottrarre il tempo da un tempo posixlt mantenendo la sua classe in r?
Domanda
Sto manipolando un po ' POSIXlt
Oggetti datetime. Ad esempio, vorrei aggiungere un'ora:
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"
Il fatto è che voglio new.lt
essere un POSIXlt
oggetto. So che potrei usare as.POSIXlt
per convertirlo a POSIXlt
, ma esiste un modo più elegante ed efficiente per raggiungere questo obiettivo?
Soluzione
Risposta breve: no
Risposta lunga:
POSIXct
e POSIXlt
Gli oggetti sono due tipi specifici del più generale POSIXt
Classe (non in un senso ereditario strettamente orientato agli oggetti, ma in un senso di implementazione orientato quasi agli oggetti). Codice cambia liberamente tra questi. Quando aggiungi a un POSIXlt
oggetto, la funzione effettiva utilizzata è +.POSIXt
, non uno specifico per POSIXlt
. All'interno di questa funzione, l'argomento viene convertito in a POSIXct
e poi affrontato (aggiunto a).
Inoltre, POSIXct
è il numero di secondi da una data e ora specifiche. POSIXlt
è un elenco di parti della data (secondi, minuti, ore, giorno del mese, mese, anno, giorno della settimana, giorno dell'anno, informazioni DST), quindi aggiungerlo direttamente non ha alcun senso. Convertendolo in diversi secondi (POSIXct
) e aggiungere a ciò ha senso.
Altri suggerimenti
POSIXct
-Il gli oggetti di classe sono internamente un valore numerico che consente calcoli numerici. POSIXlt
-Objects sono elenchi interni. Purtroppo per i tuoi desideri, Ops.POSIXt
(che è quello che viene chiamato quando usi "+") costringe a posixCT con questo codice:
if (inherits(e1, "POSIXlt") || is.character(e1))
e1 <- as.POSIXct(e1)
Fortunatamente, se lo desideri e un'ora c'è una pratica alternativa all'aggiunta di 3600. Usa invece la struttura dell'elenco e aggiungi 1 all'elemento ora:
> my.lt$hour <- my.lt$hour +1
> my.lt
[1] "2010-01-09 23:00:00"
Questo approccio è molto utile quando vuoi evitare spinose domande sui cambiamenti di DST, almeno se vuoi aggiungere giorni per darti lo stesso orario.
Modifica (aggiungendo il codice di @sunt che lo dimostra Ops.POSIXlt
è attento con il tempo "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"
Potrebbe non essere significativamente più elegante, ma
seq.POSIXt( from=Sys.time(), by="1 hour", length.out=2 )[2]
IMHO è più descrittivo di
Sys.time()+3600; # 60 minutes * 60 seconds
Perché il codice stesso documenta che stai andando per un "seq" uence ha incrementato "di 1 ora", ma è una questione di gusti. Funziona bene su Posixlt, ma nota che restituisce un posixct in entrambi i casi. Funziona anche per "giorni". Vedere Aiuto (seq.PoPixt) per i dettagli su come gestisce mesi, risparmio diurno, ecc.
?POSIXlt
te lo dice:
Qualsiasi conversione che deve andare tra le due classi di data-tempo richiede un fuso orario: la conversione da "Posixlt" a "PosixCt" convaliderà i tempi nel fuso orario selezionato.
Quindi immagino che 3600 non sia un POSIXlt
Oggetto, c'è una conversione automatica.
Rimanerei con semplice:
new.lt = as.POSIXlt(my.lt + 3600)
class(new.lt)
[1] "POSIXlt" "POSIXt"
Non è così tanto da aggiungere as.POSIXlt
Prima dell'operazione di tempo.