Gibt es eine bessere Art und Weise von der UTC-Zeit zu Epoch Zeit zu konvertieren?

StackOverflow https://stackoverflow.com/questions/4194340

  •  11-10-2019
  •  | 
  •  

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 ich UTCTime bekommen kann.
  • Mit utcTimeToPOSIXSeconds ich eine POSIXTime
  • bekommen
  • Mit einem POSIXTime kann ich mehr oder weniger erhalten eine EpochTime

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)

War es hilfreich?

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top