2

I am trying to create a form, that will send back an object with a timestamp. Right now, the input format must be yyyy-MM-dd HH:mm:ss, I want the timestamp to be entered in the format dd.MM.yyyy HH:mm - how can I change the input format?

The object class:

public class Test {
    private Timestamp dateStart;

    public Timestamp getDateStart() {
        return dateStart;
    }
    public void setDateStart(Timestamp dateStart) {
        this.dateStart = new Timestamp(dateStart.getTime());
    }
}

The controller method:

@RequestMapping(value="test", method = RequestMethod.POST)
public View newTest(@ModelAttribute("test") Test test, Model model) {
    //save the Test object
}

The jsp form:

<form:form action="service/test" method="post" modelAttribute="test">
    <form:input type="text" path="dateStart" />
</form:form>

I get this error, when the format isn't right:

Field error in object 'test' on field 'dateStart': rejected value [22.05.2012 14:00]; codes [typeMismatch.test.dateStart,typeMismatch.dateStart,typeMismatch.java.sql.Timestamp,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [test.dateStart,dateStart]; arguments []; default message [dateStart]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.sql.Timestamp' for property 'dateStart'; nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value "22.05.2012 14:00" from type 'java.lang.String' to type 'java.sql.Timestamp'; nested exception is java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]]
2
  • Maybe this will help you: stackoverflow.com/questions/10565481 Commented May 13, 2012 at 14:31
  • Thank you very much, it really helped - I will post the answer for other users. Commented May 13, 2012 at 14:44

2 Answers 2

11

Thanks to Tomasz I got the answer, I have to add a binder method to the controller:

@InitBinder
public void binder(WebDataBinder binder) {binder.registerCustomEditor(Timestamp.class,
    new PropertyEditorSupport() {
        public void setAsText(String value) {
            try {
                Date parsedDate = new SimpleDateFormat("dd.MM.yyyy HH:mm").parse(value);
                setValue(new Timestamp(parsedDate.getTime()));
            } catch (ParseException e) {
                setValue(null);
            }
        }
    });
}
Sign up to request clarification or add additional context in comments.

Comments

0

FYI, here is the code for a complete Timestamp custom editor (it supports getAsText() too), courtesy of http://adfinmunich.blogspot.com/2011/04/how-to-write-sqltimestamppropertyeditor.html, just change DEFAULT_BATCH_PATTERN to match your desired date/timestamp pattern, OR send the desired pattern when you construct the SqlTimestampPropertyEditor:

package org.springframework.beans.custompropertyeditors;

import java.beans.PropertyEditorSupport;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;

/**
 * Property editor for java.sql.Timestamp, supporting SimpleDateFormat.
 * 
 * Using default Constructor uses the pattern yyyy-MM-dd
 * Using the constructor with String, you can use your own pattern.
 * 
 */
public class SqlTimestampPropertyEditor extends PropertyEditorSupport {

public static final String DEFAULT_BATCH_PATTERN = "yyyy-MM-dd";

private final SimpleDateFormat sdf;

/**
 * uses default pattern yyyy-MM-dd for date parsing.
 */
public SqlTimestampPropertyEditor() {
    this.sdf = new SimpleDateFormat(SqlTimestampPropertyEditor.DEFAULT_BATCH_PATTERN);
}

/**
 * Uses the given pattern for dateparsing, see {@link SimpleDateFormat} for allowed patterns.
 * 
 * @param pattern
 *            the pattern describing the date and time format
 * @see SimpleDateFormat#SimpleDateFormat(String)
 */
public SqlTimestampPropertyEditor(String pattern) {
    this.sdf = new SimpleDateFormat(pattern);
}

/**
 * @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
 */
@Override
public void setAsText(String text) throws IllegalArgumentException {

    try {
        setValue(new Timestamp(this.sdf.parse(text).getTime()));
    } catch (ParseException ex) {
        throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);
    }
}

/**
 * Format the Timestamp as String, using the specified DateFormat.
 */
@Override
public String getAsText() {
    Timestamp value = (Timestamp) getValue();
    return (value != null ? this.sdf.format(value) : "");
}
}

To use this class, you would define the following @InitBinder:

@InitBinder
public void binder(WebDataBinder binder) {binder.registerCustomEditor(Timestamp.class,
    new org.springframework.beans.custompropertyeditors.SqlTimestampPropertyEditor();}

If you want to use a non-default date/timestamp pattern, supply it in the constructor to the SqlTimestampPropertyEditor, so for this particular example you could use:

@InitBinder
public void binder(WebDataBinder binder) {binder.registerCustomEditor(Timestamp.class,
    new org.springframework.beans.custompropertyeditors.SqlTimestampPropertyEditor("dd.MM.yyyy HH:mm");}

1 Comment

I would not recommend doing it like this, because you use the same instance of SimpleDateFormat for parsing, which is not thread safe (stackoverflow.com/questions/6840803/…). Sure the structure of the code is better organized, but it is unsafe, unless you create a new SimpleDateFormat for every request.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.