Haskell and Time

I’ve found myself getting confused over the Data.Time modules a few times now. Today I wanted to do something that I ought to be simple both to do (it was) and find out how to do (it wasn’t, at least not for me). I thought I’d write it down, because I’m bound to forget about it otherwise, and it might be helpful for some other poor soul out there.

I wanted to store a date in a database (SQLite) using Haskell (HDBC). Since I’m only interested in the date and not the time I chose to represent it in Haskell as a Date.Time.Calendar.Day. For Day 0 means 1858-11-17. HDBC on the other hand needs the date in seconds since epoch (1970-01-01 00:00 UTC), which conveniently can be represented with a single Integer. Time.Data.Clock.POSIX contains a few handy functions to convert between POSIXTime (NominalDiffTime) and UTCTime. However, there are no special functions for converting between an Integer and NominalDiffTime. The way I found was to do it via the class types that NominalDiffTime implements.

First I thought that Enum might offer the solution, but my experiments with that was a bit confusing:

> pt <- getPOSIXTime
1221603766.526661s
> fromEnum pt
4118657661830593344
> toEnum 4118657661830593344 :: POSIXTime 
4118657.661830593344s

Not really the result I had hoped for. No, instead the function to use to get the Integer is floor, and the only way I found to convert a NominalDiffTime from an Integer is to go via a Ratio:

> fromRational (1221603766 % 1) :: POSIXTime
1221603766s

Have I missed something or is this the best way to achieve this?

Share

5 Comments

  1. You can use fromInteger from the Num class:

    > fromInteger 42 :: POSIXTime
    42s
    
  2. fromIntegral 1221603766 :: POSIXTime seems to work too, though it isn’t much shorter.

  3. I don’t understand how to do this conversion, please, explain:

    fromInteger 43 :: POSIXTime 43s

    but

    getPOSIXTime >>= (return . fromInteger)

    :1:28: Couldn’t match expected type time-1.1.2.2:Data.Time.Clock.UTC.NominalDiffTime' against inferred typeInteger’

    or another example

    Prelude Data.Time.Clock.POSIX> a <- getPOSIXTime Prelude Data.Time.Clock.POSIX> :type a a :: POSIXTime Prelude Data.Time.Clock.POSIX> fromInteger a

    :1:12: Couldn’t match expected type Integer' against inferred typePOSIXTime’

  4. @Mechanic, I think you’ve got it the wrong way around. One would use fromInteger to convert an integer to POSIXTime.

    In both your examples you are trying pass a POSIXTime to fromInteger, as expected you get type errors when you do that.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>