I am using Yesod on my first site and I have a list of news items:
NewsItem
date UTCTime default=CURRENT_TIME
title String
content String
author String
which are retrieved in my handler:
newsitems <- runDB $ selectList [] [Desc NewsItemDate]
and ultimately used in my template:
$if null newsitems
<p>No news.
$else
$forall Entity id entry <- newsitems
<article>
<h4>#{newsItemDate entry}
<p>#{newsItemContent entry}
But I get an error about datatypes:
Handler/Home.hs:20:11:
No instance for (Text.Blaze.ToMarkup
time-1.4:Data.Time.Clock.UTC.UTCTime)
arising from a use of `toHtml'
Possible fix:
add an instance declaration for
(Text.Blaze.ToMarkup time-1.4:Data.Time.Clock.UTC.UTCTime)
In the first argument of `toWidget', namely
`toHtml (newsItemDate entry_a6ev)'
In a stmt of a 'do' block:
toWidget (toHtml (newsItemDate entry_a6ev))
In the expression:
do { toWidget
((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
"<article><h4>");
toWidget (toHtml (newsItemDate entry_a6ev));
toWidget
((Text.Blaze.Internal.preEscapedText . Data.Text.pack)
"</h4>\
\<p>");
toWidget (toHtml (newsItemContent entry_a6ev));
.... }
So I figure I would go ahead and add to my Import.hs:
import Data.Time (UTCTime)
import Data.Time.Format (formatTime)
import Text.Blaze (ToMarkup, toMarkup)
import Text.Blaze.Internal (string)
import System.Locale (defaultTimeLocale)
-- format date as 26 July 2012
instance ToMarkup UTCTime where
toMarkup a = string (formatTime defaultTimeLocale "%e %B %Y" a)
Which does compile, but gives me an error at runtime in the browser:
Internal Server Error
PersistMarshalError "Expected UTCTime, received PersistText \"2012-08-30\""
So I am not sure how to solve this, any ideas?
EDIT: Source code to the site in case it is needed or curious: https://github.com/iaefai/socrsite
I'm pretty sure you could just use show in the hamlet? That's atleast what I've done...
I've run into this instance thing before, and as this guy describes here it's something like this:
[1] http://fpcomplete.com/ten-things-you-should-know-about-haskell-syntax/
Without investigating the actual error, I think your approach is not great. You will very likely eventually want several ways of formatting a
UTCTime
, after all, the type is there to store times, not just dates. By giving aToMarkup UTCTime
instance, you fix this globally.I would recommend to write functions
renderAsDate :: UTCDate -> HTML
,renderAsTime :: UTCDate -> HTML
etc. and use them in your template, e.g.#{renderAsDate (newsItemDate entry)}
.But this won’t solve the runtime error, which comes from the serialization layer and is likely independent of your templates.