2016-09-16 15 views
7

Mam następujący problem: kolumna daty w danych, które otrzymuję, zawiera daty, które nie istnieją z powodu czasu letniego. (Na przykład 2015-03-29 02:00 nie istnieje w czasie środkowoeuropejskim, ponieważ zegar jest ustawiany bezpośrednio od 01:59 do 03:00, ponieważ DST zaczyna obowiązywać w tym dniu)Czy istnieje niezawodny sposób wykrywania obiektów POSIXlt reprezentujących czas, który nie istnieje z powodu DST?

Czy istnieje łatwy i niezawodny sposób ustalenia, czy data jest ważna w odniesieniu do czasu letniego?

Nie jest to trywialne ze względu na właściwości klas datetime.

# generating the invalid time as POSIXlt object 
test <- strptime("2015-03-29 02:00", format="%Y-%m-%d %H:%M", tz="CET") 

# the object seems to represent something at least partially reasonable, notice the missing timezone specification though 
test 
# [1] "2015-03-29 02:00:00" 

# strangely enough this object is regarded as NA by is.na 
is.na(test) 
# [1] TRUE 

# which is no surprise if you consider: 
is.na.POSIXlt 
# function (x) 
# is.na(as.POSIXct(x)) 

as.POSIXct(test) 
# [1] NA 

# inspecting the interior of my POSIXlt object: 
unlist(test) 
# sec min hour mday mon year wday yday isdst zone gmtoff 
# "0" "0" "2" "29" "2" "115" "0" "87" "-1"  ""  NA 

więc najprostszym sposobem myślałem o to, by sprawdzić pole obiektu POSIXltisdst, pomoc dla POSIXt opisuje złożony sposób następujący:

isdst
Daylight Saving Time flag. Pozytywny, jeśli obowiązujący, zero, jeśli nie, ujemny, jeśli nie jest znany.

sprawdza pole isdst Zapisz w tym sensie, że to pole jest tylko -1 jeżeli data jest nieważne z powodu zmiany czasu letniego lub może być -1 z innych powodów?

Informacje o wersji, platformy i lokalizacji

R.version 
# _       
# platform  x86_64-w64-mingw32   
# arch   x86_64      
# os    mingw32      
# system   x86_64, mingw32    
# status          
# major   3       
# minor   3.1       
# year   2016       
# month   06       
# day   21       
# svn rev  70800      
# language  R       
# version.string R version 3.3.1 (2016-06-21) 
# nickname  Bug in Your Hair    
Sys.getlocale() 
# [1] "LC_COLLATE=German_Austria.1252;LC_CTYPE=German_Austria.1252;LC_MONETARY=German_Austria.1252;LC_NUMERIC=C;LC_TIME=English_United States.1252" 
+2

Nie mogę odtworzyć Twojego przykładu. Kiedy wykonuję twój kod, nie otrzymuję 'is.na (test) FALSE', ale' TRUE' i otrzymuję CEST strefy czasowej podczas wykonywania 'testu'. Dwie możliwości: (1) Sys.getlocale(), (2) Jakiej wersji R używasz? –

+0

'is.na (test)' powinno być 'TRUE' Używam' Sys.getlocale ("LC_TIME") '' "German_Austria.1252" 'ale przykład okazuje się taki sam, jeśli robię' Sys.setlocale ("LC_TIME", "german") 'jak również' Sys.setlocale ("LC_TIME", "english") 'ustawienie strefy czasowej w strptime powinno zająć się wyborem właściwej strefy czasowej. R-wersja to: R wersja 3.3.1 (2016-06-21) działająca: x86_64-w64-mingw32 (64-bitowy Windows 7) – snaut

+2

Zgadnij, że jest zależny od systemu operacyjnego i nie mogę odtworzyć Twojego przykładu. Co się stanie, jeśli spróbujesz 'as.POSIXct (test)'? Jestem na Linuksie i zauważyłem, że obiekty "POSIXlt" czasami reprezentują nieprawidłowe czasy, podczas gdy 'POSIXct' nie. Jeśli spróbuję 'as.POSIXct (test)' otrzymam '2015-03-29 01:00:00 CET', tj. Datetime jest poprawiony. Być może możesz uzyskać swój test próbując 'identyczny (jak .OSIXlt (jak .OSIXct (test)), test)'. – nicola

Odpowiedz

1

Instrukcja mówi, że strptime nie sprawdza, czy istnieją czasy w konkretnej strefy czasowej z powodu przejścia do/z czasu letniego (?strptime). Również instrukcja mówi, że as.POSIXct dokonuje tej walidacji, więc zgodnie z instrukcją, należy sprawdzić wynikowy obiekt POSIXct dla NA (?asPOSIXct), który wskazywałby nieistniejący czas, jak pokazano w przykładzie pytania. Wynik jest jednak OS specyficzne dla czasów, które istnieją dwa razy w strefie czasowej (?asPOSIXct):

Pamiętaj, że w większości stref czasowych nie występują kilka razy, a niektóre występują dwa razy z powodu przejścia z/na „światło dzienne oszczędności "(znany również jako" lato "). strptime nie sprawdza takich czasów (nie zakłada określonej strefy czasowej), ale dokona tego konwersja przez as.POSIXct.

i

Jednym z problemów jest to, co dzieje się na przemian do iz DST, na przykład w Wielkiej Brytanii

as.POSIXct(strptime("2011-03-27 01:30:00", "%Y-%m-%d %H:%M:%S")) as.POSIXct(strptime("2010-10-31 01:30:00", "%Y-%m-%d %H:%M:%S"))

są odpowiednio nieważny (zegary poszedł naprzód w 1:00 GMT do 2:00 BST) i niejednoznaczne (zegary wróciły o 2:00 BST do 1:00 GMT). To, co dzieje się w takich przypadkach, zależy od systemu operacyjnego: należy oczekiwać, że pierwsza będzie "NA", ale druga może być interpretowana jako BST lub GMT (a wspólne systemy dają obie możliwe wartości).

+0

Ponadto, rzadko istnieje powód do używania 'POSIXlt'. POSIXct jest zwykle preferowany. – Roland

+0

Niestety, to nie odpowiada na moje pytanie, ale raczej ponownie przedstawia problem. Muszę niezawodnie wykrywać nieistniejące daty w serii dat analizowanych w pliku CSV i muszę je odróżnić od innych wartości NA, które wynikają z pustych łańcuchów itp. Parsowanie bezpośrednio do POSIXct nie jest możliwe, przynajmniej nie w standardowych bibliotekach . – snaut

1

Wartość as.POSIXct(test) wydaje się być zależne od platformy, dodając warstwę złożoności do uzyskania niezawodną metodę. Na mojej maszynie Windows (R 3.3.1), as.POSIXct(test) produkuje NA, jak również zgłaszane przez OP. Jednak na mojej platformie Linux (ta sama wersja R), mam następujące:

times = c ("2015-03-29 01:00", 
      "2015-03-29 02:00", 
      "2015-03-29 03:00") 

test <- strptime(times, format="%Y-%m-%d %H:%M", tz="CET") 

test 
#[1] "2015-03-29 01:00:00 CET" "2015-03-29 02:00:00 CEST" "2015-03-29 03:00:00 CEST" 
as.POSIXct(test) 
#[1] "2015-03-29 01:00:00 CET" "2015-03-29 01:00:00 CET" "2015-03-29 03:00:00 CEST" 
as.character(test) 
#[1] "2015-03-29 01:00:00" "2015-03-29 02:00:00" "2015-03-29 03:00:00" 
as.character(as.POSIXct(test)) 
#[1] "2015-03-29 01:00:00" "2015-03-29 01:00:00" "2015-03-29 03:00:00" 

Jedna rzecz, że możemy polegać na nie jest rzeczywista wartość as.POSIXct(test), ale że będzie się różnić od test gdy test jest nieważna data/czas:

(as.character(test) == as.character(as.POSIXct(test))) %in% TRUE 
# TRUE FALSE TRUE 

nie jestem pewien, że jest to bezwzględnie konieczne as.character tutaj, ale to po prostu aby upewnić się, że nie godziłoby innych dziwnych zachowań obiektów POSIX.

+0

Myślę, że skopiowałeś dane wyjściowe z 'testu' dwa razy zamiast wklejać dane wyjściowe z' as.POSIXct (test) ', również ostatni test daje mi' # TRUE NA TRUE'. Ale '(jako .charakter (test) == jak.character (jak.POSIXct (test)))% w% TRUE' działa dla mnie. Nie piękne rozwiązanie, ale działa. Dziękuję Ci. – snaut

+0

Dzięki @snaut, dobry połów. Wkleiłem poprawne wyjście, ale zachowanie 'as.POSIXct' jest wyraźnie zależne od platformy. Odpowiednio zaktualizowałem odpowiedź – dww

Powiązane problemy