如何将 Vaadin DateField 绑定到 LocalDateTime

How to bind a Vaadin DateField to a LocalDateTime

Vaadin docs 展示了如何将 DateFieldjava.util.Date 一起使用,但我想将 DateFieldBeanFieldGroup 绑定到一个 bean 属性 Java 8 类型 java.time.LocalDateTime。我怎样才能做到这一点?

似乎 Vaadin Converter 是要走的路:

package org.raubvogel.fooddiary.util;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Locale;

import com.vaadin.data.util.converter.Converter;

/**
 * Provides a conversion between old {@link Date} and new {@link LocalDateTime} API.
 */
public class LocalDateTimeToDateConverter implements Converter<Date, LocalDateTime> {

    private static final long serialVersionUID = 1L;

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

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

}

灵感来自 this link which converts between LocalDate and Date. The converter needs to be set to the DateField via setConverter or alternatively via a converter factory

这将是一个从 LocalDate 到 LocalDateTime 的 Vaadin 8 转换器:

package de.company.project.portal.application.views.documents;

import com.vaadin.data.Converter;
import com.vaadin.data.Result;
import com.vaadin.data.ValueContext;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Objects;

/**
 * A converter that converts between <code>LocalDate</code> and
 * <code>LocalDateTime</code>.
 *
 * Created from Vaadin v.8.13.0 LocalDateTimeToDateConverter
 */
public class LocalDateToLocalDateTimeConverter
        implements Converter<LocalDate, LocalDateTime>
{
    private ZoneId zoneId;

    /**
     * Creates a new converter using the given time zone.
     *
     * @param zoneId
     *            the time zone to use, not <code>null</code>
     */
    public LocalDateToLocalDateTimeConverter(ZoneId zoneId) {
        this.zoneId = Objects.requireNonNull(zoneId,
                "Zone identifier cannot be null");
    }


    @Override
    /** @return LocalDateTime from LocalDate with atTime(0,0,0,0) */
    public Result<LocalDateTime> convertToModel(LocalDate localDate,
                                                ValueContext context)
    {
        if (localDate == null) {
            return Result.ok(null);
        }
        return Result.ok(LocalDateTime.from(localDate.atTime(0,0,0,0))); //(hrs, mins, sec, nano sec)
    }


    @Override
    public LocalDate convertToPresentation(LocalDateTime localDateTime,
                                           ValueContext context)
    {
        if (localDateTime == null) {
            return null;
        }
        return LocalDate.from(localDateTime.atZone(zoneId));
    }

}

在 Binder 中使用 DTO DocumentDto:

public void bindCreationDate(DateField field) {
    forField(field.getField())
            .withConverter(new LocalDateToLocalDateTimeConverter(ZoneId.systemDefault()))
            .bind(DocumentDto::getCreationDate, DocumentDto::setCreationDate);
}