Steffen Harbich
Steffen Harbich

Reputation: 2759

How to bind a Vaadin DateField to a LocalDateTime

The Vaadin docs show how to use the DateField with java.util.Date but I want to bind the DateField with a BeanFieldGroup to a bean property of Java 8 type java.time.LocalDateTime. How can I achieve that?

Upvotes: 4

Views: 2992

Answers (2)

kitekat
kitekat

Reputation: 321

This would be a Vaadin 8 Converter from LocalDate to LocalDateTime:

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

}

Usage in Binder with DTO DocumentDto:

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

Upvotes: 1

Steffen Harbich
Steffen Harbich

Reputation: 2759

Seems like a Vaadin Converter is the way to go:

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

}

Inspired by 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.

Upvotes: 5

Related Questions