diff options
author | Ahmed Ashour <asashour@yahoo.com> | 2017-09-28 11:37:32 +0200 |
---|---|---|
committer | Henri Sara <henri.sara@gmail.com> | 2017-09-28 12:37:32 +0300 |
commit | c520767bf156c54a9d1a9f69f0aa78bc3b835b3f (patch) | |
tree | 208c6d8679708a6cc9e8b425d86fe10f2abeedc9 /client | |
parent | 131601de3693655387313e47e887f593c32fa625 (diff) | |
download | vaadin-framework-c520767bf156c54a9d1a9f69f0aa78bc3b835b3f.tar.gz vaadin-framework-c520767bf156c54a9d1a9f69f0aa78bc3b835b3f.zip |
Handle 'z' (timezone) in AbstractDateField.setDateFormat() (#8844)
Diffstat (limited to 'client')
3 files changed, 118 insertions, 3 deletions
diff --git a/client/src/main/java/com/vaadin/client/DateTimeService.java b/client/src/main/java/com/vaadin/client/DateTimeService.java index 2e9627a5a5..577b079ce2 100644 --- a/client/src/main/java/com/vaadin/client/DateTimeService.java +++ b/client/src/main/java/com/vaadin/client/DateTimeService.java @@ -21,6 +21,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.google.gwt.i18n.client.LocaleInfo; +import com.google.gwt.i18n.client.TimeZone; import com.google.gwt.i18n.shared.DateTimeFormat; import com.vaadin.shared.ui.datefield.DateResolution; @@ -50,7 +51,7 @@ public class DateTimeService { * Creates a new date time service with a given locale. * * @param locale - * e.g. fi, en etc. + * e.g. {@code fi}, {@code en}, etc. * @throws LocaleNotLoadedException */ public DateTimeService(String locale) throws LocaleNotLoadedException { @@ -305,10 +306,40 @@ public class DateTimeService { * @return */ public String formatDate(Date date, String formatStr) { + return formatDate(date, formatStr, null); + } + + /** + * Check if format contains the month name. If it does we manually convert + * it to the month name since DateTimeFormat.format always uses the current + * locale and will replace the month name wrong if current locale is + * different from the locale set for the DateField. + * + * MMMM is converted into long month name, MMM is converted into short month + * name. '' are added around the name to avoid that DateTimeFormat parses + * the month name as a pattern. + * + * z is converted into the time zone name, using the specified + * {@code timeZoneJSON} + * + * @param date + * The date to convert + * @param formatStr + * The format string that might contain {@code MMM} or + * {@code MMMM} + * @param timeZone + * The {@link TimeZone} used to replace {@code z}, can be + * {@code null} + * + * @return the formatted date string + * @since 8.2 + */ + public String formatDate(Date date, String formatStr, TimeZone timeZone) { /* * Format month and day names separately when locale for the * DateTimeService is not the same as the browser locale */ + formatStr = formatTimeZone(date, formatStr, timeZone); formatStr = formatMonthNames(date, formatStr); formatStr = formatDayNames(date, formatStr); @@ -406,6 +437,66 @@ public class DateTimeService { return formatStr; } + private String formatTimeZone(Date date, String formatStr, + TimeZone timeZone) { + // if 'z' is found outside quotes and timeZone is used + if (getIndexOf(formatStr, 'z') != -1 && timeZone != null) { + return replaceTimeZone(formatStr, timeZone.getShortName(date)); + } + return formatStr; + } + + /** + * Replaces the {@code z} characters of the specified {@code formatStr} with + * the given {@code timeZoneName}. + * + * @param formatStr + * The format string, which is the pattern describing the date + * and time format + * @param timeZoneName + * the time zone name + * @return the format string, with {@code z} replaced (if found) + */ + private static String replaceTimeZone(String formatStr, + String timeZoneName) { + + // search for 'z' outside the quotes (inside quotes is escaped) + int start = getIndexOf(formatStr, 'z'); + if (start == -1) { + return formatStr; + } + + // if there are multiple consecutive 'z', treat them as one + int end = start; + while (end + 1 < formatStr.length() + && formatStr.charAt(end + 1) == 'z') { + end++; + } + return formatStr.substring(0, start) + "'" + timeZoneName + "'" + + formatStr.substring(end + 1); + } + + /** + * Returns the first index of the specified {@code ch}, which is outside the + * quotes. + */ + private static int getIndexOf(String str, char ch) { + boolean inQuote = false; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c == '\'') { + if (i + 1 < str.length() && str.charAt(i + 1) == '\'') { + i++; + } else { + inQuote ^= true; + } + } else if (c == ch && !inQuote) { + return i; + } + } + return -1; + } + /** * Replaces month names in the entered date with the name in the current * browser locale. diff --git a/client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java b/client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java index c9c6df01f4..206709c86d 100644 --- a/client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java +++ b/client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java @@ -27,6 +27,7 @@ import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.i18n.client.TimeZone; import com.google.gwt.user.client.ui.TextBox; import com.vaadin.client.BrowserInfo; import com.vaadin.client.Focusable; @@ -70,6 +71,9 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> /** For internal use only. May be removed or replaced in the future. */ private String formatStr; + /** For internal use only. May be removed or replaced in the future. */ + private TimeZone timeZone; + public VAbstractTextualDate(R resoluton) { super(resoluton); text = new TextBox(); @@ -177,7 +181,7 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> String formatString = getFormatString(); if (currentDate != null) { dateText = getDateTimeService().formatDate(currentDate, - formatString); + formatString, timeZone); } else { dateText = ""; } @@ -195,7 +199,10 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> Roles.getTextboxRole() .removeAriaReadonlyProperty(text.getElement()); } + } + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; } @Override @@ -220,7 +227,7 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> // FIXME: Add a description/example here of when this is // needed text.setValue(getDateTimeService().formatDate(getDate(), - getFormatString()), false); + getFormatString(), timeZone), false); } // remove possibly added invalid value indication diff --git a/client/src/main/java/com/vaadin/client/ui/datefield/AbstractTextualDateConnector.java b/client/src/main/java/com/vaadin/client/ui/datefield/AbstractTextualDateConnector.java index fb3351ea4f..81eea0e71e 100644 --- a/client/src/main/java/com/vaadin/client/ui/datefield/AbstractTextualDateConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/datefield/AbstractTextualDateConnector.java @@ -16,8 +16,11 @@ package com.vaadin.client.ui.datefield; +import com.google.gwt.i18n.client.TimeZone; +import com.google.gwt.i18n.client.TimeZoneInfo; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.UIDL; +import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.ui.VAbstractTextualDate; import com.vaadin.shared.ui.datefield.AbstractTextualDateFieldState; @@ -71,4 +74,18 @@ public abstract class AbstractTextualDateConnector<R extends Enum<R>> return (AbstractTextualDateFieldState) super.getState(); } + @OnStateChange("timeZoneJSON") + private void onTimeZoneJSONChange() { + TimeZone timeZone; + String timeZoneJSON = getState().timeZoneJSON; + if (timeZoneJSON != null) { + TimeZoneInfo timeZoneInfo = TimeZoneInfo + .buildTimeZoneData(timeZoneJSON); + timeZone = TimeZone.createTimeZone(timeZoneInfo); + } else { + timeZone = null; + } + getWidget().setTimeZone(timeZone); + } + } |