From 7d6408ac56c70c8463856a52d831629d8513625c Mon Sep 17 00:00:00 2001 From: Ezra Epstein Date: Mon, 3 Jul 2017 00:45:19 -0700 Subject: [PATCH] Use ZoneId rather than ZoneOffset for conversion (#9620) Use ZoneId rather than ZoneOffset for conversion between model (Date) and presentation of LocalDateTime. LocalDateToDateConverter (correctly) uses ZoneId, whereas LocalDateTimeToDateConverter (incorrectly) used a ZoneOffset. This fix aligns the two Converter implementations and makes the latter one more robust. A ZoneOffset is a fixed time difference, e.g., +07:00, whereas a time zone - represented by a ZoneId - is more dynamic, including features like Daylight-Savings Time. A ZoneId returns one or more ZoneOffsets via its ZoneRules method. (ZoneOffsets have trivial ZoneRules that simply return the ZoneOffset.) Since the date/time being displayed may be from any date on the calendar, the ZoneOffset imposes a negative limitation. Using ZoneId instead gets us past that limitation and allows a more robust set of conversion rules. Fixes #9594 --- .../LocalDateTimeToDateConverter.java | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/server/src/main/java/com/vaadin/data/converter/LocalDateTimeToDateConverter.java b/server/src/main/java/com/vaadin/data/converter/LocalDateTimeToDateConverter.java index e5fa45a3fb..167c452eaf 100644 --- a/server/src/main/java/com/vaadin/data/converter/LocalDateTimeToDateConverter.java +++ b/server/src/main/java/com/vaadin/data/converter/LocalDateTimeToDateConverter.java @@ -17,7 +17,7 @@ package com.vaadin.data.converter; import java.time.Instant; import java.time.LocalDateTime; -import java.time.ZoneOffset; +import java.time.ZoneId; import java.util.Date; import java.util.Objects; @@ -35,41 +35,35 @@ import com.vaadin.ui.InlineDateTimeField; * @author Vaadin Ltd * @since 8.0 */ -public class LocalDateTimeToDateConverter - implements Converter { +public class LocalDateTimeToDateConverter implements Converter { - private ZoneOffset zoneOffset; + private ZoneId zoneId; /** * Creates a new converter using the given time zone. * - * @param zoneOffset - * the time zone offset to use, not null + * @param zoneId the time zone to use, not null */ - public LocalDateTimeToDateConverter(ZoneOffset zoneOffset) { - this.zoneOffset = Objects.requireNonNull(zoneOffset, - "Zone offset cannot be null"); + public LocalDateTimeToDateConverter(ZoneId zoneId) { + this.zoneId = Objects.requireNonNull(zoneId, "Zone identifier cannot be null"); } @Override - public Result convertToModel(LocalDateTime localDate, - ValueContext context) { + public Result convertToModel(LocalDateTime localDate, ValueContext context) { if (localDate == null) { return Result.ok(null); } - return Result.ok(Date.from(localDate.toInstant(zoneOffset))); + return Result.ok(Date.from(localDate.atZone(zoneId).toInstant())); } @Override - public LocalDateTime convertToPresentation(Date date, - ValueContext context) { + public LocalDateTime convertToPresentation(Date date, ValueContext context) { if (date == null) { return null; } - return Instant.ofEpochMilli(date.getTime()).atZone(zoneOffset) - .toLocalDateTime(); + return Instant.ofEpochMilli(date.getTime()).atZone(zoneId).toLocalDateTime(); } } -- 2.39.5