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 } }