2010-11-16 30 views
8

Tôi muốn đặt thời gian sửa đổi của tệp cho thời gian tôi nhận được từ dữ liệu exif.Có cách nào tốt hơn để chuyển đổi từ UTCTime sang EpochTime?

Để có được thời gian từ exif, tôi thấy:

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

Để thiết lập thời gian sửa đổi tập tin, tôi thấy:

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

Giả sử tôi không tìm thấy một Time in Exif, tôi cần phải chuyển đổi một chuỗi thành một EpochTime.

  • Với parseTime Tôi có thể nhận được UTCTime.
  • Với utcTimeToPOSIXSeconds tôi có thể có được một POSIXTime
  • Với POSIXTime tôi nhiều hơn hoặc ít hơn có thể nhận được một EpochTime

Để chuyển đổi từ một UTCTime để EpochTime typechecks này, nhưng tôi không chắn rằng nó là đúng:

fromIntegral . fromEnum . utcTimeToPOSIXSeconds $ etime 

Đây là một phần của hàm getTime sẽ trả về thời gian từ Exif dữ liệu, nếu prese nt, nếu thời gian sửa đổi của tập tin:

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) 

Câu hỏi của tôi là

Có/cách đơn giản hơn để chuyển đổi thời gian? (Có thể sử dụng libaries khác nhau)

Trả lời

8

Data.Time là thư viện thời gian được hỗ trợ tốt nhất, vì vậy tôi chắc chắn sẽ đồng ý với lựa chọn của bạn sử dụng nó để phân tích chuỗi đại diện của ngày và thời gian mà bạn nhận ra các dữ liệu Exif.

Bạn có chắc chắn cần đặt thời gian sửa đổi của tệp không? Điều đó thật bất thường. Nhưng nếu có, thì có, bạn sẽ cần sử dụng các thư viện System.Posix trên hệ thống Posix.

Nếu bạn chỉ cần đọc việc sửa đổi một tập tin, bạn sẽ được tốt hơn bằng cách sử dụng chức năng chung chung hơn System.Directory.getModificationTime. Thật không may, chức năng đó cũng sử dụng thư viện thời gian không chuẩn, System.Time từ gói dài hạn không được chấp nhận old-time trong trường hợp này. Vì vậy, bạn vẫn cần phải thực hiện một số mưu đồ tương tự.

Chuyển đổi của bạn từ POSIXTime thành EpochTime xảy ra là OK trong trường hợp cụ thể này, nhưng nói chung đó không phải là cách lý tưởng để thực hiện.

Loại EpochTime, a.k.một loại time_t từ C, không không hỗ trợ bất kỳ cách trực tiếp nào được xây dựng trong Haskell mà không qua giá trị tích phân, mặc dù bản thân nó không nhất thiết phải tách rời tùy thuộc vào hệ điều hành của bạn. Bạn có thể đi qua C bằng cách sử dụng FFI nếu những phân số tiềm năng của một giây là quan trọng đối với bạn. Đây chắc chắn không quan trọng, bởi vì bạn sẽ nhận được giây từ thông số định dạng %S mà không thể có phần phân đoạn. Dù sao. bạn vẫn sẽ cần phải thực hiện một số loại làm tròn hoặc cắt ngắn để lấy từ loại không thể tách rời UTCTime thành EpochTime.

Bạn hiện chỉ đang sử dụng ví dụ Enum của POSIXTime để thực hiện việc làm tròn/cắt ngắn cho bạn, tuy nhiên quyết định đó sẽ thay đổi. Một lần nữa, trong trường hợp này, nó không thực sự quan trọng, bởi vì chúng tôi xảy ra để biết rằng giá trị sẽ là tích phân. Nhưng nói chung, tốt hơn hết nên tự mình chỉ định nó một cách rõ ràng bằng cách sử dụng floor, ceiling hoặc round. Ví dụ:

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

(Lưu ý rằng bạn không cần phải viết ra một cách rõ ràng case, bạn có thể sử dụng chức năng maybe từ Prelude.)

Chú ý rằng tôi cũng dứt khoát sử dụng fromInteger để đẩy chuyển đổi thông qua loại Integer. Nếu bạn muốn đi qua Int thay vì (xem ra cho "Năm 2038 Vấn đề" trên máy 32-bit), tôi sẽ xác định một chức năng chuyển đổi riêng biệt để làm cho rằng rõ ràng:

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

tôi sao chép hình ảnh từ một hệ thống tập tin khác, sử dụng copyFile ngày của tập tin bị mất, vì vậy tôi cần phải đặt nó trở lại để phù hợp với thời điểm bức ảnh được chụp. –

+0

@David V .: Vâng, điều đó sẽ làm được. 'System.Posix' nó là. – Yitz

8

Bạn cũng có thể sử dụng Data.Convertible.convert (từ gói convertible):

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

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

Data.Convertible gọn gàng. Nếu bạn gặp sự cố phụ thuộc với nó: cabal install convertible --reinstall – Joe

Các vấn đề liên quan