Dealing with Dates and Times (5/365)

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

  1. There is no type to represent seconds since Unix epoch (I’ll call this Unix time).
  2. There is no simple way to read and write Day, UTC datetime, Local time in the ISO8601 format.
  3. 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

ghci> readISO8601 "2016-05-03T12:05:23" :: Maybe UTCTime

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"

And converting

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

For fun

ghci> let Just t = readISO8601 "2016-05-03T12:05:23Z" :: Maybe UnixTime
ghci> mapM_ (putStrLn . showISO8601) . take 10 . enumFrom $ t
This entry was posted in Haskell and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s