Gibt es eine bessere Art und Weise von der UTC-Zeit zu Epoch Zeit zu konvertieren?
Frage
Ich mag die Zeit eine Datei Änderungszeit einstellen I von EXIF-Daten einsehen.
Um die Zeit von exif, ich gefunden:
Graphics.Exif.getTag :: Exif -> String -> IO (Maybe String)
, um die Datei-Änderungszeit einzustellen, fand ich:
System.Posix.Files.setFileTimes :: FilePath -> EpochTime -> EpochTime -> IO ()
Unter der Annahme, ich eine Zeit in Exif finden tun, ich brauche einen String in einen EpochTime zu konvertieren.
- Mit
parseTime
ichUTCTime
bekommen kann. - Mit
utcTimeToPOSIXSeconds
ich einePOSIXTime
bekommen
- Mit einem
POSIXTime
kann ich mehr oder weniger erhalten eineEpochTime
Um von einem UTCTime
wandeln diese typechecks EpochTime
, aber ich bin nicht
sicher, es ist richtig:
fromIntegral . fromEnum . utcTimeToPOSIXSeconds $ etime
Dies ist Teil einer Funktion getTime, die die Zeit von Exif zurück Daten, falls vorhanden, ansonsten der Zeitpunkt der letzten Änderung der Datei:
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)
Meine Frage ist
Gibt es eine bessere / einfachere Möglichkeit, die Zeit zu konvertieren? (Möglicherweise unterschiedlich libaries verwenden)
Lösung
Data.Time
ist die beste unterstützte Zeitbibliothek, so dass ich auf jeden Fall zustimmen würde
Ihre Wahl, um es für die Verwendung der String-Darstellung von Datum und Uhrzeit zu analysieren
dass Sie der Exif-Daten erhalten werden.
Sind Sie sicher, Sie müssen Satz die Änderungszeit einer Datei? Das ist unüblich. Aber wenn ja, dann ja, müssen Sie die System.Posix
Bibliotheken auf einem Posix-System verwenden.
Wenn Sie nur zu lesen die Änderung einer Datei,
wäre es besser, die generische Funktion
System.Directory.getModificationTime
. Leider diese Funktion
verwendet auch eine Nicht-Standard-Zeitbibliothek, System.Time
aus dem
old-time
Paket in diesem Fall lang veraltet.
So Sie noch brauchen würden einige ähnlichen Machenschaften zu tun.
Ihre Umwandlung von POSIXTime
zu EpochTime
passiert zu sein
OK in diesem speziellen Fall, aber im Allgemeinen ist es nicht ideal Weg zu gehen.
Der EpochTime
Typ,
a.k.a der time_t
Typ von C, tut
keine direkte Art und Weise unterstützt über, ohne dabei in Haskell gebaut werden
ein fester Wert, auch wenn es sich nicht notwendigerweise integral
je nach Betriebssystem.
Sie könnten über C unter Verwendung des FFI gehen, wenn diese potenziellen Bruchteile einer Sekunde sind
Ihnen wichtig.
Hier das ist sicherlich nicht wichtig, denn
Sie bekommen die Sekunden von einem %S
Formatparameter, die keinen Bruchteil haben können.
Wie auch immer. Sie werden immer noch eine Art von Runden oder Kürzen tun müssen
aus dem nicht ganzzahligen UTCTime
Typ EpochTime
zu erhalten.
Sie sind zur Zeit nur mit der Enum
Instanz von POSIXTime
das zu tun
Rundungs ??/ Abschneide
aber für Sie ist, entscheidet sie.
Wieder ist es in diesem speziellen Fall spielt keine Rolle, wirklich, weil wir passieren
zu wissen, dass der Wert integriert sein wird.
Aber im Allgemeinen ist es besser, es zu spezifizieren
sich ausdrücklich von floor
, ceiling
oder round
verwenden. Z.B.
return $ maybe ftime (fromInteger . round . utcTimeToPOSIXSeconds) etime
(Beachten Sie, dass Sie nicht brauchen, um explizit die case
zu schreiben,
Sie können die maybe
Funktion aus dem Prelude verwenden.)
Beachten Sie, dass ich auch fromInteger
explizit bin mit der schieben
Umwandlung durch
der Integer
Typ. Wenn Sie über Int
gehen wollen statt (achten Sie auf
das „Jahr 2038-Problem“ auf 32-Bit-Maschinen), würde ich eine Definition
getrennte Konvertierungsfunktion das klar zu machen:
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
Andere Tipps
Sie können auch Data.Convertible.convert
verwenden (aus dem umwandelbar Paket):
import Data.Convertible (convert)
import System.Posix.Types (EpochTime(..))
import Data.Time.Clock (UTCTime(..))
utcTimeToEpochTime :: UTCTime -> EpochTime
utcTimeToEpochTime = convert