2010-11-16 17 views
8

Chcę ustawić czas modyfikacji pliku na czas, który otrzymałem z danych exif.Czy istnieje lepszy sposób na konwersję z UTCTime na EpochTime?

Aby uzyskać czas z EXIF, stwierdziliśmy:

Graphics.Exif.getTag :: Exif -> String -> IO (Maybe String) 

Aby ustawić czas modyfikacji pliku, znalazłem:

System.Posix.Files.setFileTimes :: FilePath -> EpochTime -> EpochTime -> IO() 

Zakładając robię znaleźć taki czas w Exif, muszę przekonwertuj ciąg na epochTime.

  • Z parseTime mogę uzyskać UTCTime.
  • Z utcTimeToPOSIXSeconds mogę uzyskać POSIXTime
  • dysponujący POSIXTime mogę bardziej lub mniej uzyskać EpochTime

o przekonwertowaniu UTCTime do EpochTime tego typechecks, ale nie jestem pewien, że to poprawne:

fromIntegral . fromEnum . utcTimeToPOSIXSeconds $ etime 

jest częścią getTime funkcji, które zwracają czas z Exif danych, jeśli prese nt, inaczej czas modyfikacji pliku:

getTime (path,stat) = do 
let ftime     = modificationTime $ stat 
    err (SomeException _) = return ftime 
time <- liftIO $ handle err $ do 
    exif <- Exif.fromFile path 
    let getExifTime = MaybeT . liftIO . Exif.getTag exif 
    res <- runMaybeT $ do 
    tmp <- msum . map getExifTime $ [ "DateTimeOriginal","DateTimeDigitized", "DateTime" ] 
    MaybeT . return . parseTime defaultTimeLocale "%Y:%m:%d %H:%M:%S" $ tmp 
    case res of 
    Nothing -> return ftime 
    Just etime -> return . fromIntegral . fromEnum . utcTimeToPOSIXSeconds $ etime 
return (path,time) 

Moje pytanie brzmi

Czy istnieje lepszy/prostszy sposób przekonwertować czas? (Być może przy użyciu różnych bibliotekami)

Odpowiedz

8

Data.Time jest najlepiej obsługiwana biblioteka czas, więc na pewno zgadzam się z wyboru go używać do analizowania ciąg znaków reprezentujący datę i czas że wydostać się z danych EXIF.

Czy na pewno chcesz ustawić czas modyfikacji pliku? To niespotykane. Ale jeśli tak, to tak, musisz użyć bibliotek System.Posix w systemie Posix.

Jeśli trzeba tylko czytać modyfikację pliku, można byłoby lepiej wyłączyć za pomocą funkcji bardziej ogólny System.Directory.getModificationTime. Niestety, funkcja wykorzystuje w tym przypadku niestandardową bibliotekę czasową, System.Time z długo-przestarzałego zestawu old-time. Więc nadal musisz zrobić kilka podobnych machinacji.

Konwersja z POSIXTime na EpochTime jest w tym przypadku OK. OK, ale ogólnie nie jest to idealna droga.

Typ EpochTime, a.k.typ time_t z C, czy nie obsługuje żadnego bezpośredniego sposobu budowania w Haskell bez przechodzenia przez wartości integralnej, nawet jeśli sam w sobie niekoniecznie jest integralny w zależności od systemu operacyjnego. Możesz przejść przez C używając FFI, jeśli te potencjalne ułamki sekundy są ważne dla Ciebie. To z pewnością nie jest ważne, ponieważ dostajesz sekundy z parametru formatu %S, który nie może zawierać części ułamkowej. W każdym razie. nadal będziesz musiał wykonać jakiś zaokrąglenie lub obcięcie , aby uzyskać od nieintegralnego typu UTCTime do EpochTime.

Aktualnie tylko za pomocą wystąpienie POSIXTimeEnum zrobić zaokrąglania/obcinanie dla ciebie, jednak postanowi. Ponownie, w tym konkretnym przypadku tak naprawdę nie ma to znaczenia, ponieważ zdarza się, wiedzieć, że wartość będzie integralna. Ogólnie rzecz biorąc, lepiej jest podać go samodzielnie, korzystając z , ceiling lub round. Np

return $ maybe ftime (fromInteger . round . utcTimeToPOSIXSeconds) etime 

(Zauważ, że nie trzeba wypisać case wyraźnie, można użyć funkcji maybe z Prelude).

Zauważ, że ja też jawnie przy użyciu fromInteger do pchania Konwersja poprzez typ . Jeśli chcesz, aby przejść przez Int zamiast (uważaj na z „problem roku 2038” na maszynach 32-bitowych), chciałbym zdefiniować oddzielną funkcję konwersji żeby to było jasne:

return $ maybe ftime utcTimeToEpochTime etime 
... 

-- Convert from UTCTime to EpochTime via Int 
utcTimeToEpochTime :: UTCTime -> EpochTime 
utcTimeToEpochTime = fromIntegral . toSecs 
    where 
    toSecs :: UTCTime -> Int 
    toSecs = round . utcTimeToPOSIXSeconds 
+0

mam kopiowania zdjęć z systemu plików do innego, używając CopyFile data pliku nie jest stracone, więc trzeba ustawić ją z powrotem w celu dopasowania do czasu wykonania zdjęcia. –

+0

@ David V .: Tak, to zrobi. 'System.Posix' to jest. – Yitz

8

Można również użyć Data.Convertible.convert (z pakietu convertible):

import Data.Convertible (convert) 
import System.Posix.Types (EpochTime(..)) 
import Data.Time.Clock (UTCTime(..)) 

utcTimeToEpochTime :: UTCTime -> EpochTime 
utcTimeToEpochTime = convert 
+1

Data.Convertible jest czysty. Jeśli napotkasz na problem z zależnościami: cabal install convertible --reinstall – Joe

Powiązane problemy