代码之家  ›  专栏  ›  技术社区  ›  David V.

有没有更好的方法从现在到将来?

  •  8
  • David V.  · 技术社区  · 14 年前

    我想把文件的修改时间设置为从ExIF数据中获得的时间。

    从EXIF获得时间,我发现:

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

    要设置文件修改时间,我发现:

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

    假设我在EXIF中找到了一个时间,我需要把一个字符串转换成一个划时代的。

    • parseTime 我可以得到一个 UTCTime .
    • utcTimeToPOSIXSeconds 我可以得到一个 POSIXTime
    • 用一个 位置时间 我或多或少能得到一个 EpochTime

    外景 时代 这是支票,但我不是 当然是对的:

    fromIntegral . fromEnum . utcTimeToPOSIXSeconds $ etime
    

    这是一个函数GETTIME的一部分,它将返回EXIF的时间。 数据,如果存在,否则文件的修改时间:

    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)
    

    我的问题是

    有没有更好/更简单的方法来转换时间?(可能使用不同的libaries)

    2 回复  |  直到 14 年前
        1
  •  8
  •   Yitz    14 年前

    Data.Time 是最受支持的时间库,所以我绝对同意 您可以选择使用它来解析日期和时间的字符串表示形式 你可以从EXIF数据中出来。

    你确定你需要 设置 文件的修改时间?这很不寻常。但如果是,那么是的,你需要使用 System.Posix Posix系统上的库。

    如果你只需要 阅读 文件的修改, 最好使用更通用的函数 System.Directory.getModificationTime . 不幸的是,这个功能 也使用非标准时间库, System.Time 从 长期弃用 old-time 在这种情况下打包。 所以你还是需要做一些类似的阴谋。

    你的转变 POSIXTime EpochTime 碰巧 在这种情况下是可以的,但一般来说这不是理想的方法。

    这个 时代 类型, a、 卡拉 time_t 从C输入,does 不支持在Haskell中不经过 整数值,即使它本身不一定是整数值 取决于你的操作系统。 如果一秒钟的潜在分数是 对你很重要。 这当然不重要,因为 你从一个 %S 格式参数,不能有小数部分。 无论如何。您仍然需要进行某种舍入或截断 从非积分中得到 UTCTime 键入到 时代 .

    您当前正在使用 Enum 实例 位置时间 去做 舍入/截断 对你来说,不管它怎么决定。 再说一次,在这种情况下,这并不重要,因为我们碰巧 知道这个值是整数。 但总的来说,最好具体说明 通过使用 floor , ceiling ,或 round . 例如。,

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

    (请注意,您不需要写出 case 明确地, 你可以使用 maybe 前奏曲的功能。)

    注意,我还显式地使用 fromInteger 推动 转换通过 这个 Integer 键入。如果你想通过 Int 相反(注意 在32位机器上的“2038年问题”,我将定义 单独的转换函数来说明这一点:

      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
    
        2
  •  8
  •   Thedward    13 年前

    你也可以使用 Data.Convertible.convert (来自 convertible 包装):

    import Data.Convertible (convert)
    import System.Posix.Types (EpochTime(..))
    import Data.Time.Clock (UTCTime(..))
    
    utcTimeToEpochTime :: UTCTime -> EpochTime
    utcTimeToEpochTime = convert