Установите диапазон в Vaadin DateField при использовании конвертера

Я использую DateField в Vaadin с конвертером, чтобы включить использование LocalDateTime пакета java.time.

Когда я использую Converter и ограничиваю DateField с помощью setRangeEnd(), DateField всегда показывает UserError с сообщением «Дата вне допустимого диапазона». Без конвертера работает нормально.

Мой конвертер:

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, где используется 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());

Кто-нибудь знает, как я могу установить диапазон при использовании конвертера?


person Peter Lustig    schedule 24.11.2016    source источник
comment
Вы можете использовать RangeValidator например: dateField.addValidator(new RangeValidator<LocalDateTime>("Not in range", LocalDateTime.class, null, lastAvailableDataDate). Чтобы это работало, вам нужно удалить dateField.setRangeStart(..) и dateField.setRangeEnd(..), что будет означать, что курсор без ввода не будет отображаться в даты, превышающие конец диапазона, поэтому пользователь может выбрать их (хотя появится сообщение проверки). По этой причине я не хочу добавлять это в качестве ответа   -  person Ian A    schedule 24.11.2016
comment
@Ian Ян, спасибо за ответ. Основная причина использования методов setRange — показать пользователю информацию о том, что нет доступных данных для невыбираемых дат. В настоящее время я решил эту проблему, расширив класс DateField. Хорошо, что мне больше не нужен преобразователь.   -  person Peter Lustig    schedule 24.11.2016


Ответы (1)


Мой текущий способ решить эту проблему — расширить класс DateField.

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());
}
}

Теперь конвертер больше не нужен, а методы get/setDate() соответствуют нашим методам свингового выбора даты. Для нашего случая это может быть лучшим решением.

person Peter Lustig    schedule 24.11.2016