I'm working on a Grails project with Freemarker and am having trouble rendering a date from the data model. I start put placing a date into the model
def dataModel = [:]
def dataDate = new Date().parse("yyyy-MM-dd","2015-08-20")
dataModel.put("someDate",dataDate)
I then loop through the dataModel to verify the data types
dataModel.each { name, value ->
println "${name} : ${value} (Value is type: ${value.getClass()})"
}
For this my output is: someDate : Thu Aug 20 00:00:00 CDT 2015 (Value is type: class java.util.Date)
Next I set up my confiuration and try to process the template
Configuration cfg = new Configuration(Configuration.VERSION_2_3_22)
cfg.setDefaultEncoding("UTF-8")
def ftlTemplate = new Template("name", new StringReader("${someDate}"), cfg)
Writer out = new StringWriter()
ftlTemplate.process(dataModel, out)
output = out.toString()
At this point I receive the following error
ERROR freemarker.runtime - Error executing FreeMarker template
Message: Can't convert the date-like value to string because it isn't known if it's a date (no time part), time or date-time value.
The blamed expression:
==> someDate [in template "name" at line 1, column 3]
I've found a Freemarker engine online here: http://freemarker-online.kenshoo.com/ and if I run the same datamodel and template through that the ouput I receive is: Aug 20, 2015
Can anyone point out where I am going wrong? I would like to render the output like that online engine does.
Thanks
The problem is (as the error message states) is that it's technically impossible to decide in general, if a java.util.Date
stands for a date-only, date-time or time-only value. This is a technical fact that's outside FreeMarker. FreeMarker offers these ways to handle this problem:
Use ?date
, ?time
and ?datetime
operators to give FreeMarker a hint in the template. See: http://freemarker.org/docs/ref_builtins_date.html#ref_builtin_date_datetype
Use java.sql.Date
and java.sql.Timestamp
and java.sql.Timestamp
, where there's no such ambiguity. (Beware with Timestamp
's funny fraction second handling though.)
Wrap the values manually into TemplateDateModel
, where you can specify which kind of value it is. Then drop the TemplateDateModel
into the data-model.