aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorAhmed Ashour <asashour@yahoo.com>2017-09-28 11:37:32 +0200
committerHenri Sara <henri.sara@gmail.com>2017-09-28 12:37:32 +0300
commitc520767bf156c54a9d1a9f69f0aa78bc3b835b3f (patch)
tree208c6d8679708a6cc9e8b425d86fe10f2abeedc9 /server
parent131601de3693655387313e47e887f593c32fa625 (diff)
downloadvaadin-framework-c520767bf156c54a9d1a9f69f0aa78bc3b835b3f.tar.gz
vaadin-framework-c520767bf156c54a9d1a9f69f0aa78bc3b835b3f.zip
Handle 'z' (timezone) in AbstractDateField.setDateFormat() (#8844)
Diffstat (limited to 'server')
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractDateField.java51
-rw-r--r--server/src/main/java/com/vaadin/util/TimeZoneUtil.java150
2 files changed, 201 insertions, 0 deletions
diff --git a/server/src/main/java/com/vaadin/ui/AbstractDateField.java b/server/src/main/java/com/vaadin/ui/AbstractDateField.java
index bc6b5f49a8..b5f11f7122 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractDateField.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractDateField.java
@@ -19,6 +19,7 @@ import java.io.Serializable;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
+import java.time.ZoneId;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.util.Calendar;
@@ -56,6 +57,7 @@ import com.vaadin.shared.ui.datefield.DateFieldConstants;
import com.vaadin.shared.ui.datefield.DateResolution;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.util.TimeZoneUtil;
/**
* A date editor component with {@link LocalDate} as an input value.
@@ -95,6 +97,8 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
*/
private String dateFormat;
+ private ZoneId zoneId;
+
private boolean lenient = false;
private String dateString = "";
@@ -445,6 +449,53 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
}
/**
+ * Sets the {@link ZoneId}, which is used when {@code z} is included inside
+ * the {@link #setDateFormat(String)}.
+ *
+ * @param zoneId
+ * the zone id
+ * @since 8.2
+ */
+ public void setZoneId(ZoneId zoneId) {
+ if (zoneId != this.zoneId
+ || (zoneId != null && !zoneId.equals(this.zoneId))) {
+ updateTimeZoneJSON(zoneId, getLocale());
+ }
+ this.zoneId = zoneId;
+ }
+
+ private void updateTimeZoneJSON(ZoneId zoneId, Locale locale) {
+ String timeZoneJSON;
+ if (zoneId != null && locale != null) {
+ timeZoneJSON = TimeZoneUtil.toJSON(zoneId, locale);
+ } else {
+ timeZoneJSON = null;
+ }
+ getState().timeZoneJSON = timeZoneJSON;
+ }
+
+ @Override
+ public void setLocale(Locale locale) {
+ Locale oldLocale = getLocale();
+ if (locale != oldLocale
+ || (locale != null && !locale.equals(oldLocale))) {
+ updateTimeZoneJSON(getZoneId(), locale);
+ }
+ super.setLocale(locale);
+ }
+
+ /**
+ * Returns the {@link ZoneId}, which is used when {@code z} is included
+ * inside the {@link #setDateFormat(String)}.
+ *
+ * @return the zoneId
+ * @since 8.2
+ */
+ public ZoneId getZoneId() {
+ return zoneId;
+ }
+
+ /**
* Specifies whether or not date/time interpretation in component is to be
* lenient.
*
diff --git a/server/src/main/java/com/vaadin/util/TimeZoneUtil.java b/server/src/main/java/com/vaadin/util/TimeZoneUtil.java
new file mode 100644
index 0000000000..ec3d28e730
--- /dev/null
+++ b/server/src/main/java/com/vaadin/util/TimeZoneUtil.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.util;
+
+import java.io.Serializable;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.zone.ZoneOffsetTransition;
+import java.time.zone.ZoneRules;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import elemental.json.JsonArray;
+import elemental.json.JsonObject;
+import elemental.json.impl.JreJsonFactory;
+import elemental.json.impl.JsonUtil;
+
+/**
+ * Utilities related to {@link com.google.gwt.i18n.client.TimeZone}.
+ *
+ * @author Vaadin Ltd
+ * @since 8.2
+ */
+public final class TimeZoneUtil implements Serializable {
+
+ /**
+ * The start year used to send the time zone transition dates.
+ */
+ private static final int STARTING_YEAR = 1980;
+
+ /**
+ * Till how many years from now, should we send the time zone transition
+ * dates.
+ */
+ private static final int YEARS_FROM_NOW = 20;
+
+ private TimeZoneUtil() {
+ // Static utils only
+ }
+
+ /**
+ * Returns a JSON string of the specified {@code zoneId} and {@link Locale},
+ * which is used in
+ * {@link com.google.gwt.i18n.client.TimeZone#createTimeZone(String)}.
+ *
+ * @param zoneId
+ * the {@link ZoneId} to get the daylight transitions from
+ * @param locale
+ * the locale used to determine the short name of the time zone
+ *
+ * @return the encoded string
+ */
+ public static String toJSON(ZoneId zoneId, Locale locale) {
+ if (zoneId == null || locale == null) {
+ return null;
+ }
+ ZoneRules rules = zoneId.getRules();
+ TimeZone timeZone = TimeZone.getTimeZone(zoneId);
+ List<Long> transitionsList = new ArrayList<>();
+
+ TimeZoneInfo info = new TimeZoneInfo();
+
+ int endYear = LocalDate.now().getYear() + YEARS_FROM_NOW;
+ if (timeZone.useDaylightTime()) {
+ for (int year = STARTING_YEAR; year <= endYear; year++) {
+ ZonedDateTime i = LocalDateTime.of(year, 1, 1, 0, 0)
+ .atZone(zoneId);
+ while (true) {
+ ZoneOffsetTransition t = rules
+ .nextTransition(i.toInstant());
+ if (t == null) {
+ break;
+ }
+ i = t.getInstant().atZone(zoneId);
+ if (i.toLocalDate().getYear() != year) {
+ break;
+ }
+ long epocHours = Duration
+ .ofSeconds(t.getInstant().getEpochSecond())
+ .toHours();
+ long duration = Math.max(t.getDuration().toMinutes(), 0);
+ transitionsList.add(epocHours);
+ transitionsList.add(duration);
+ }
+ }
+ }
+ info.id = zoneId.getId();
+ info.transitions = transitionsList.stream().mapToLong(l -> l).toArray();
+ info.std_offset = (int) Duration.ofMillis(timeZone.getRawOffset())
+ .toMinutes();
+ info.names = new String[] {
+ timeZone.getDisplayName(false, TimeZone.SHORT, locale),
+ timeZone.getDisplayName(false, TimeZone.LONG, locale),
+ timeZone.getDisplayName(true, TimeZone.SHORT, locale),
+ timeZone.getDisplayName(true, TimeZone.LONG, locale) };
+
+ return stringify(info);
+ }
+
+ private static String stringify(TimeZoneInfo info) {
+ JreJsonFactory factory = new JreJsonFactory();
+ JsonObject object = factory.createObject();
+ object.put("id", info.id);
+ object.put("std_offset", info.std_offset);
+ object.put("names", getArray(factory, info.names));
+ object.put("transitions", getArray(factory, info.transitions));
+ return JsonUtil.stringify(object);
+ }
+
+ private static JsonArray getArray(JreJsonFactory factory, long[] array) {
+ JsonArray jsonArray = factory.createArray();
+ for (int i = 0; i < array.length; i++) {
+ jsonArray.set(i, array[i]);
+ }
+ return jsonArray;
+ }
+
+ private static JsonArray getArray(JreJsonFactory factory, String[] array) {
+ JsonArray jsonArray = factory.createArray();
+ for (int i = 0; i < array.length; i++) {
+ jsonArray.set(i, array[i]);
+ }
+ return jsonArray;
+ }
+
+ private static class TimeZoneInfo implements Serializable {
+ String id;
+ int std_offset;
+ String[] names;
+ long[] transitions;
+ }
+}