haxx populi

Better structured date editor for Grails

by jja on
Topics:

It's really surprising and annoying that the default structured editor for dates and times in Grails is so limited. It only allows one to edit (or enter) time information down to the minute. Seconds and smaller are ignored, even though the editor specifically returns an epoch time in milliseconds with the getTime() method! The default editor also only works for java.util.Date and java.sql.Date -- not the also common java.sql.Timestamp.

I've created a new editor that works for all 3 types mentioned and allows one to edit/enter more complete time information, including seconds (yeah!), millisecond or nanosecond, and also allows the use of an "epoch" time field to edit a raw integer.

See the editor code at StructuredDateOrTimestampEditor.java (GitHub) or download StructuredDateOrTimestampEditor.java

I setup the editor in my own registrar class, e.g. src/groovy/mypackage/CustomPropertyEditorRegistrar.groovy where I make several editor customizations:

import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import java.beans.PropertyEditor;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.math.BigDecimal;
import java.util.Locale;
import edu.ucar.eol.spring.SqlTimestampPropertyEditor;
import edu.ucar.eol.grails.StructuredDateOrTimestampEditor;
public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
  public void registerCustomEditors(PropertyEditorRegistry registry) {
    registry.registerCustomEditor(java.sql.Timestamp.class, new StructuredDateOrTimestampEditor());
    registry.registerCustomEditor(java.util.Date.class, new StructuredDateOrTimestampEditor());
    registry.registerCustomEditor(java.sql.Date.class, new StructuredDateOrTimestampEditor());
  }
}

and then register the bean with Spring grails-app/conf/spring/resources.groovy:

beans = {
  CustomPropertyEditorRegistrar(mypackage.CustomPropertyEditorRegistrar)
}

Finally, to make use of it you'll need the proper HTML in your view. I'm also using Joda time, and modified the Grails plugin's taglib at DateTimeTagLib.groovy (GitHub) or download DateTimeTagLib.groovy

It has all worked great so far.

Sorry, I don't have any real tests but here are some things you can try in your grails shell :

sed = new net.sinequanon.grails.StructuredDateOrTimestampEditor("yyyy-MM-dd HH:mm:ss.S")
ts = sed.assemble(java.sql.Timestamp, [epoch:'1'])
===> 1970-01-01 00:00:00.001
ts = sed.assemble(java.sql.Timestamp, [:])
===> null
ts = sed.assemble(java.sql.Timestamp, [year:'2014', millisecond:'123'])
===> 2014-01-01 00:00:00.123
ts = sed.assemble(java.sql.Timestamp, [year:'2014', nanosecond:'456'])
===> 2014-01-01 00:00:00.000000456
// nanosecond takes precedence over millisecond
ts = sed.assemble(java.sql.Timestamp, [year:'2014', millisecond:'123', nanosecond:'456'])
===> 2014-01-01 00:00:00.000000456
ts = sed.assemble(java.sql.Timestamp, [year:'2014', epoch:'5', millisecond:'123'])
===> 1970-01-01 00:00:00.005
// epoch is milliseconds and sets the time before nanosecond overwrites the fractional portion
ts = sed.assemble(java.sql.Timestamp, [year:'2014', epoch:'5', nanosecond:'456'])
===> 1970-01-01 00:00:00.000000456

References

(comments are closed)