[2.1.x] Date format in Form

1,480 views
Skip to first unread message

Jens Alm

unread,
May 22, 2013, 1:49:56 PM5/22/13
to play-fr...@googlegroups.com
I have spent the better part of 2 days trying to find a solution to this, if it is out there - it is hiding well.

I have a Model like this:

@Entity
public TestModel{
   public String name;
 
   @Temporal(TemporalType.TIMESTAMP)
   public Date date;
   ...
}

I wrap this in a form and send it to the view like normal. In the view I am trying to get the date to be formatted with I18N. 

@helper.inputText(myForm("date")) or @helper.inputDate(myForm("date")) both output the date as 2013-05-22 no matter what I try. Is there a way to do this without writing several custom formatters (java.util.Date, java.sql.Date, java.sql.Timestamp to cover all variations)?

My knowledge of scala extends as far as creating templates for Play! and no further so I am unable to look through the source code and figure it out for myself in the short term at least.

Please help.

Vikram

unread,
May 22, 2013, 2:12:11 PM5/22/13
to play-fr...@googlegroups.com
Have you tried built in date formatter-

@Formats.DateTime(pattern="dd/MM/yyyy")

@Temporal(TemporalType.TIMESTAMP)

   public Date date;


Vikram

Jens Alm

unread,
May 22, 2013, 2:53:51 PM5/22/13
to play-fr...@googlegroups.com
Thank you for the suggestion but it only helps part of the problem. Putting the pattern on the Model object makes it hard coded to a certain language/format. I18N should be able to handle several types of formats. I would like the solution if I could put a key in that annotation, like so:

@Formats.DateTime(patternKey="date.format")

and that is looked up in the messages like all other properties.

Guillaume Bort

unread,
May 23, 2013, 3:35:08 AM5/23/13
to play-fr...@googlegroups.com
The formatters are totally pluggable. You can create them in your app (or in an external library) to add more constraints/formats/validations to your app.

Here is the default @Formats.DateTime one:


and the corresponding annotation:



--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Guillaume Bort, http://guillaume.bort.fr

Jens Alm

unread,
May 23, 2013, 1:55:59 PM5/23/13
to play-fr...@googlegroups.com
I have actually tried that and it doesn't work to override the definition of the Date.class converter. I have debugged the application and I think there is a bug here.

The first call to Formatters.print() calls FormattingConversionService.canConvert() which in turn iterates through all formatters that have a matching TypeDescriptor. If your new formatter annotation is not on the first field of that type, the formatter used will be the default built in Play! one which is fine in this instance. The next field, if it has the new formatter annotation will get the same formatter as the first because by now it has been cached as THE formatter for this type by the ConversionService.
I am sure this works great with new custom types which don't have a built in converter in Play! but it doesn't work for overriding. Please correct me if I'm wrong, I would love to be. Below is an excerpt of the code I have tried (and failed with). Most of this is copy/paste except for the key/messages part.

Annotation:
    @Target({FIELD})
   @Retention(RUNTIME)
   @play.data.Form.Display(name="format.date", attributes={"key"})
   public static @interface DateTimePattern {
      String key();
    }


Formatter:
    public static class AnnotationDateFormatter extends Formatters.AnnotationFormatter<DateTimePattern,Date> {

        public Date parse(DateTimePattern annotation, String text, Locale locale) throws java.text.ParseException {
            if(text == null || text.trim().isEmpty()) {
                return null;
            }
            SimpleDateFormat sdf = new SimpleDateFormat(Messages.get(new Lang(locale.getLanguage(), locale.getCountry()), annotation.key()), locale);
            sdf.setLenient(false);
            return sdf.parse(text);
        }

        public String print(DateTimePattern annotation, Date value, Locale locale) {
            if(value == null) {
                return "";
            }
            return new SimpleDateFormat(Messages.get(new Lang(locale.getLanguage(), locale.getCountry()), annotation.key()), locale).format(value);
        }

    }




In Global:
    @Override
  public void onStart(Application application) {
      super.onStart(application);

      Formatters.register(Date.class, new AnnotationDateFormatter());
 }


Guillaume Bort

unread,
May 23, 2013, 2:19:05 PM5/23/13
to play-fr...@googlegroups.com

But do you apply the @DateTimePattern annotation on your field?

Jens Alm

unread,
May 23, 2013, 3:31:54 PM5/23/13
to play-fr...@googlegroups.com
Yepp, I do.

    @Formats.DateTimePattern(key="date.format")
    @Temporal(TemporalType.TIMESTAMP)
    public Date periodEnd;

Jens Alm

unread,
May 27, 2013, 2:46:22 PM5/27/13
to play-fr...@googlegroups.com
So is this a defect or am I still missing something?


On Thursday, May 23, 2013 2:19:05 PM UTC-4, Guillaume Bort wrote:
Reply all
Reply to author
Forward
0 new messages