Grails has great support for type conversion on request parameters. And since Grails 2.0 the support has been extended to include dates. In our controller we can use the date() method on the params object to get a date value. The value of a request parameter is a String, so the String value is parsed to a Date object.
The default expected date format is yyyy-MM-dd HH:mm:ss.S. If we don't specify a specific date format in the date() method then this format is used. Or we can add a format to our messages.properties with the key date.<param-name>.format. Grails will first try the default format, but if the request parameter cannot be parsed to a valid Date object then Grails will do a lookup of the date format in messages.properties. Technically Grails uses the MessageSource bean to get the format, so we even can define the format per language or country.
Alternatively we can pass a date format or multiple date formats to the date() method. Grails will use these date formats to parse the request parameter into a valid Date object.
Let's show the different options we have in a simple sample controller:
// File: grails-app/controllers/param/date/SampleController.groovy
package param.date
class SampleController {
final def dateFormats = ['yyyy-MM-dd', 'yyyyMMdd']
def index() {
[
defaultFormatDate: defaultFormatDate,
defaultFormatNameDate: defaultFormatNameDate,
singleFormatDate: singleFormatDate,
multipleFormatsDate1: multipleFormatsDate1,
multipleFormatsDate2: multipleFormatsDate2
]
}
private Date getDefaultFormatDate() {
// Use default format yyyy-MM-dd HH:mm:ss.S
params.date 'defaultFormatDate'
}
private Date getDefaultFormatNameDate() {
// Lookup format with key date.defaultFormatNameDate.format
// in messages.properties: yyyy-MM-dd
params.date 'defaultFormatNameDate'
}
private Date getSingleFormatDate() {
params.date 'singleFormatDate', 'yyyyMMdd'
}
private Date getMultipleFormatsDate1() {
params.date 'multipleFormatsDate1', dateFormats
}
private Date getMultipleFormatsDate2() {
params.date 'multipleFormatsDate2', dateFormats
}
}
In messages.properties we define the format for the request parameter defaultFormatNameDate:
# File: grails-app/i18n/messages.properties ... date.defaultFormatNameDate.format=yyyy-MM-dd ...
To show that the date parsing works we write a little integration test. We need this to be an integration test, because then the lookup of the key via the MessageSource bean works.
package param.date
import org.junit.Test
class SampleControllerTests extends GroovyTestCase {
@Test
void testDateParameters() {
def controller = new SampleController()
// Set request parameters.
def params = [
defaultFormatDate: inputDateTime.format('yyyy-MM-dd HH:mm:ss.S'),
defaultFormatNameDate: inputDateTime.format('yyyy-MM-dd'),
singleFormatDate: inputDateTime.format('yyyyMMdd'),
multipleFormatsDate1: inputDateTime.format('yyyy-MM-dd'),
multipleFormatsDate2: inputDateTime.format('yyyyMMdd')
]
controller.request.parameters = params
def model = controller.index()
assertDates inputDateTime, model.defaultFormatDate
assertDates inputDate, model.defaultFormatNameDate
assertDates inputDate, model.singleFormatDate
assertDates inputDate, model.multipleFormatsDate1
assertDates inputDate, model.multipleFormatsDate2
}
private void assertDates(final Date expected, final Date controllerDate) {
assertEquals expected.toGMTString(), controllerDate.toGMTString()
}
/**
* Create Date object for January 10, 2012 14:12:01.120
*/
private Date getInputDateTime() {
final Calendar cal = Calendar.instance
cal.updated(year: 2012, month: Calendar.JANUARY, date: 10,
hours: 14, minutes: 12, seconds: 1, milliSeconds: 120)
cal.time
}
private Date getInputDate() {
final Date inputDateTime = inputDateTime
inputDateTime.clearTime()
inputDateTime
}
}