In the past, I’ve had to deal with reading, writing, and performing arithmetic on dates and times in Haskell and the experience is not a pleasant one. Actually, I’ve had to do this in PHP and Erlang and the experience is no better.
So, along the way I created some utilities to make life a little easier. I’ll take a few posts to cover them but let me start with the most common annoyances I’ve had. They are as follows
- There is no type to represent seconds since Unix epoch (I’ll call this Unix time).
- There is no simple way to read and write Day, UTC datetime, Local time in the ISO8601 format.
- Most of all, there is no easy way to convert between UTC time and Local time or Unix time.
Now, there are a few libraries to help you. Most notably,
datetime provides many of these utilities but the types are not very helpful. Believe me when I say a huge chunk of your datetime problems are solved if only you could do those three things easily and in an error-free way.
I have a single file here, that allows you to do the following. Reading
ghci> :l TimeUtils.hs ghci> readISO8601 "2016-05-03" :: Maybe Day Just 2016-05-03 ghci> readISO8601 "2016-05-03" :: Maybe UTCTime Nothing ghci> readISO8601 "2016-05-03T12:05:23" :: Maybe UTCTime Nothing ghci> readISO8601 "2016-05-03T12:05:23" :: Maybe LocalTime Just 2016-05-03 12:05:23 ghci> readISO8601 "2016-05-03T12:05:23Z" :: Maybe UTCTime Just 2016-05-03 12:05:23 UTC ghci> readISO8601 "2016-05-03T12:05:23Z" :: Maybe UnixTime Just 1462277123
ghci> showISO8601 <$> (readISO8601 "2016-05-03" :: Maybe Day) Just "2016-05-03" ghci> showISO8601 <$> (readISO8601 "2016-05-03T12:05:23Z" :: Maybe UnixTime) Just "2016-05-03T12:05:23Z"
ghci> utcToUnixTime <$> readISO8601 "2016-05-03T12:05:23Z" Just 1462277123 ghci> localTimeToUnixTime <$> readISO8601 "2016-05-03T12:05:23" Just 1462277123 ghci> (unixTimeToUTC . succ) <$> readISO8601 "2016-05-03T12:05:23Z" Just 2016-05-03 12:05:24 UTC
ghci> let Just t = readISO8601 "2016-05-03T12:05:23Z" :: Maybe UnixTime ghci> mapM_ (putStrLn . showISO8601) . take 10 . enumFrom $ t 2016-05-03T12:05:23Z 2016-05-03T12:05:24Z 2016-05-03T12:05:25Z 2016-05-03T12:05:26Z 2016-05-03T12:05:27Z 2016-05-03T12:05:28Z 2016-05-03T12:05:29Z 2016-05-03T12:05:30Z 2016-05-03T12:05:31Z 2016-05-03T12:05:32Z