2015-09-30 22 views
5

ho una colonna di data e ora in formato personaggio che assomiglia a questo:Lettura dei dati timestamp in R da più fusi orari

2015-09-24 06:00:00 UTC

2015-09- 24 05:00:00 UTC

dateTimeZone <- c("2015-09-24 06:00:00 UTC","2015-09-24 05:00:00 UTC") 

vorrei convertire questi dati di caratteri in dati in tempo utilizzando POSIXct, e se sapevo che tutto il tempo francobolli erano in UTC, vorrei fare in questo modo:

dateTimeZone <- asPOSIXct(dateTimeZone, tz="UTC") 

Tuttavia, non necessariamente so che tutto il tempo francobolli sono in UTC, quindi ho cercato

dateTimeZone <- asPOSIXct(dateTimeZodateTimeZone, format = "%Y-%m-%d %H:%M:%S %Z") 

Tuttavia, poiché strptime supporta% Z solo per l'uscita, questo restituisce il seguente errore:

Error in strptime(x, format, tz = tz) : use of %Z for input is not supported

Ho controllato la documentazione del pacchetto lubridate e non ho visto che gestisse questo problema in modo diverso rispetto a POSIXct.

È la mia unica opzione per controllare il fuso orario di ogni riga e quindi utilizzare il fuso orario appropriato con qualcosa di simile al seguente?

temp[grepl("UTC",datetimezone)] <- as.POSIXct(datetimezone, tz="UTC") 
temp[grepl("PDT",datetimezone)] <- as.POSIXct(datetimezone, tz="America/Los_Angeles") 

risposta

4

È possibile arrivarci controllando ogni riga e elaborando di conseguenza, quindi riportando tutto in un tempo UTC coerente. (#edited per includere ora corrispondere le sigle fuso orario per la specifica completa fuso orario)

dates <- c(
    "2015-09-24 06:00:00 UTC", 
    "2015-09-24 05:00:00 PDT" 
) 

#extract timezone from dates 
datestz <- vapply(strsplit(dates," "), tail, 1, FUN.VALUE="") 

## Make a master list of abbreviation to 
## full timezone names. Used an arbitrary summer 
## and winter date to try to catch daylight savings timezones. 

tzabbrev <- vapply(
    OlsonNames(), 
    function(x) c(
    format(as.POSIXct("2000-01-01",tz=x),"%Z"), 
    format(as.POSIXct("2000-07-01",tz=x),"%Z") 
), 
    FUN.VALUE=character(2) 
) 
tmp <- data.frame(Olson=OlsonNames(), t(tzabbrev), stringsAsFactors=FALSE) 
final <- unique(data.frame(tmp[1], abbrev=unlist(tmp[-1]))) 

## Do the matching: 
out <- Map(as.POSIXct, dates, tz=final$Olson[match(datestz,final$abbrev)]) 
as.POSIXct(unlist(out), origin="1970-01-01", tz="UTC") 
# 2015-09-24 06:00:00 UTC 2015-09-24 05:00:00 PDT 
#"2015-09-24 06:00:00 GMT" "2015-09-24 12:00:00 GMT" 
0

Una soluzione data.table:

library(data.table) 

data <- data.table(dateTimeZone=c("2015-09-24 06:00:00 UTC", 
            "2015-09-24 05:00:00 America/Los_Angeles")) 
data[, timezone:=tstrsplit(dateTimeZone, split=" ")[[3]]] 
data[, datetime.local:=as.POSIXct(dateTimeZone, tz=timezone), by=timezone] 
data[, datetime.utc:=format(datetime.local, tz="UTC")] 

La cosa fondamentale è quello di suddividere i dati sul campo fuso orario in modo da poter invia ogni serie di fusi orari a as.POSIXct separatamente (non sono proprio sicuro del motivo per cui lo standard as.POSIXct non ti consente di assegnargli un vettore di fusi orari, in realtà). Qui utilizzo la sintassi split-apply-combine efficiente di data.table, ma è possibile applicare la stessa idea generale con la base R o utilizzando dplyr.