In the IHP web framework, columns with the Postgres “Date” type are translated into Haskell as the Day type. Looking at the docs for Day, it isn’t exactly clear how to create a Day value from a time string. Here’s how to do this for a simple case:

parseDay :: String -> Day
parseDay = parseTimeOrError True defaultTimeLocale "%Y-%m-%d"

which will produce a Day value given a string of the form 2020-12-29. NOTE: if the string is not valid, an error will be thrown. For better error handling, use parseTimeM, which is executed in the context of any MonadFail, such as the Maybe monad:

parseDay' :: String -> Maybe Day
parseDay' = parseTimeM True defaultTimeLocale "%Y-%m-%d"

For info on all the different format options for the format string, see here.


In my application, dates from the feed I was parsing had the form 2020-12-28T16:32:12+00:00. I did not need the time info, so I could call parseDay as such:

parseDay $ takeWhile ('T' /=) (cs date)

which uses the cs function from Data.String.Conversions, included with IHP, to convert seamlessly between string types. With the Day object, we can then create an IHP record. Here’s an example from my data loading script:

itemNodeToEpisode :: ItemNode -> Episode
itemNodeToEpisode ItemNode {..} =
  newRecord @Episode
    |> set #title title
    |> set #description description
    |> set #link link
    |> set #audioLink audioLink
    |> set #date (parseDay $ takeWhile ('T' /=) (cs date))