1

I'm using a DateField in Vaadin with a Converter to enable the usage of LocalDateTime of java.time Package.

When I'm using the Converter and limit the DateField by setRangeEnd() the DateField always shows an UserError with the message 'Date is out of allowed Range'. Without using the Converter it works fine.

My Converter:

public class LocalDateTimeToDateConverter implements Converter<Date,LocalDateTime> {

    private static final long serialVersionUID = -4900262260743116965L;

    @Override
    public LocalDateTime convertToModel(Date value, Class<? extends LocalDateTime> targetType, Locale locale)
            throws com.vaadin.data.util.converter.Converter.ConversionException {

        if (value != null) {
            return value.toInstant().atZone(ZoneOffset.systemDefault()).toLocalDate().atStartOfDay();
        }

        return null;
    }

    @Override
    public Date convertToPresentation(LocalDateTime value, Class<? extends Date> targetType, Locale locale)
        throws com.vaadin.data.util.converter.Converter.ConversionException {

        if (value != null) {
            return Date.from(value.atZone(ZoneOffset.systemDefault()).toInstant());
        }

        return null;
    }

    @Override
    public Class<LocalDateTime> getModelType() {
        return LocalDateTime.class;
    }

    @Override
    public Class<Date> getPresentationType() {
        return Date.class;
    }
}

MyView where is use the DateField:

dateField = new DateField();
dateField.setDateFormat("yyyy-MM-dd");
dateField.setRangeStart(null);
dateField.setRangeEnd(Date.from(lastAvailableDataDate.atZone(ZoneId.systemDefault()).toInstant()));
dateField.setConverter(new LocalDateTimeToDateConverter());

Anyone knows how i can set the range while using the converter?

Márton
  • 105
  • 10
Peter Lustig
  • 1,585
  • 1
  • 18
  • 34
  • You could use a [RangeValidator](http://demo.vaadin.com/javadoc/com.vaadin/vaadin/7.0.0.alpha3/com/vaadin/data/validator/RangeValidator.html) e.g: `dateField.addValidator(new RangeValidator("Not in range", LocalDateTime.class, null, lastAvailableDataDate)`. For this to work you'd have to remove `dateField.setRangeStart(..)` and `dateField.setRangeEnd(..)` which would mean the "no entry" cursor would not show on dates greater than the range end, so the user could select them (although the validation message would appear). For this reason I'm reluctant to add this as an answer – Ian A Nov 24 '16 at 10:18
  • @Ian A thank you for your answer. The main reason to use the setRange methods is to show the information to the user that there is no data available for the non-selectable dates. I currently solved this issue by extending the DateField class. The good thing about it is that i don't need the converter anymore. – Peter Lustig Nov 24 '16 at 10:40

1 Answers1

0

My current way to solve this issue is to extend the DateField class.

public class MyDateField extends DateField {

private static final long serialVersionUID = -7056642919646970829L;

public MyDateField() {
    super();
}

public LocalDateTime getDate() {
    Date value = super.getValue();

    return DateToLocalDateTime(value);
}

public void setDate(LocalDateTime date) {
    super.setValue(LocalDateTimeToDate(date));
}

public void setRange(LocalDateTime start, LocalDateTime end) {

    if (start != null) {
        super.setRangeStart(LocalDateTimeToDate(start));
    } else {
        super.setRangeStart(null);
    }

    if (end != null) {
        super.setRangeEnd(LocalDateTimeToDate(end));
    } else {
        super.setRangeEnd(null);
    }
}

private Date LocalDateTimeToDate(LocalDateTime localDateTime) {
    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}

private LocalDateTime DateToLocalDateTime(Date date) {
    return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
}

Now there is no need for the converter anymore and the get/setDate() methods correspond with our swing datepicker methods. For our case this might be the best solution.

Peter Lustig
  • 1,585
  • 1
  • 18
  • 34