From 7a192a8d5f643e51837ad2ce4cba91a29c343e9d Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 24 Aug 2010 11:37:36 +0000 Subject: Fix for #5474 - DateField fails to parse month names when using custom date format svn changeset:14577/svn branch:6.4 --- .../terminal/gwt/client/DateTimeService.java | 141 +++++++++++++++++++++ .../terminal/gwt/client/ui/VTextualDate.java | 78 +++--------- 2 files changed, 157 insertions(+), 62 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/DateTimeService.java b/src/com/vaadin/terminal/gwt/client/DateTimeService.java index f572411a83..b307eaf737 100644 --- a/src/com/vaadin/terminal/gwt/client/DateTimeService.java +++ b/src/com/vaadin/terminal/gwt/client/DateTimeService.java @@ -6,6 +6,8 @@ package com.vaadin.terminal.gwt.client; import java.util.Date; +import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.i18n.client.LocaleInfo; import com.vaadin.terminal.gwt.client.ui.VDateField; /** @@ -272,4 +274,143 @@ public class DateTimeService { return weekNumber; } + /** + * 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. + * + * @param date + * The date to convert + * @param formatStr + * The format string that might contain MMM or MMMM + * @param dateTimeService + * Reference to the Vaadin DateTimeService + * @return + */ + public String formatDate(Date date, String formatStr) { + /* + * Format month names separately when locale for the DateTimeService is + * not the same as the browser locale + */ + formatStr = formatMonthNames(date, formatStr); + + // Format uses the browser locale + DateTimeFormat format = DateTimeFormat.getFormat(formatStr); + + String result = format.format(date); + + return result; + } + + private String formatMonthNames(Date date, String formatStr) { + if (formatStr.contains("MMMM")) { + @SuppressWarnings("deprecation") + String monthName = getMonth(date.getMonth()); + + if (monthName != null) { + formatStr = formatStr.replaceAll("[M]{4,}", "'" + monthName + + "'"); + } + } + + if (formatStr.contains("MMM")) { + + @SuppressWarnings("deprecation") + String monthName = getShortMonth(date.getMonth()); + + if (monthName != null) { + formatStr = formatStr.replaceAll("[M]{3,}", "'" + monthName + + "'"); + } + } + + return formatStr; + } + + /** + * Replaces month names in the entered date Parses the month name from the + * entered dat + * + * @param enteredDate + * @param formatString + * @return + */ + private String parseMonthName(String enteredDate, String formatString) { + LocaleInfo browserLocale = LocaleInfo.getCurrentLocale(); + if (browserLocale.getLocaleName().equals(getLocale())) { + // No conversion needs to be done when locales match + return enteredDate; + } + String[] browserMonthNames = browserLocale.getDateTimeConstants() + .months(); + String[] browserShortMonthNames = browserLocale.getDateTimeConstants() + .shortMonths(); + + if (formatString.contains("MMMM")) { + // Full month name + for (int i = 0; i < 12; i++) { + enteredDate = enteredDate.replaceAll(getMonth(i), + browserMonthNames[i]); + } + } + if (formatString.contains("MMM")) { + // Short month name + for (int i = 0; i < 12; i++) { + enteredDate = enteredDate.replaceAll(getShortMonth(i), + browserShortMonthNames[i]); + } + } + + return enteredDate; + } + + /** + * Parses the given date string using the given format string and the locale + * set in this DateTimeService instance. + * + * @param dateString + * Date string e.g. "1 February 2010" + * @param formatString + * Format string e.g. "d MMMM yyyy" + * @param lenient + * true to use lenient parsing, false to use strict parsing + * @return A Date object representing the dateString. Never returns null. + * @throws IllegalArgumentException + * if the parsing fails + * + */ + public Date parseDate(String dateString, String formatString, + boolean lenient) throws IllegalArgumentException { + /* DateTimeFormat uses the browser's locale */ + DateTimeFormat format = DateTimeFormat.getFormat(formatString); + + /* + * Parse month names separately when locale for the DateTimeService is + * not the same as the browser locale + */ + dateString = parseMonthName(dateString, formatString); + + Date date; + + if (lenient) { + date = format.parse(dateString); + } else { + date = format.parseStrict(dateString); + } + + // Some version of Firefox sets the timestamp to 0 if parsing fails. + if (date != null && date.getTime() == 0) { + throw new IllegalArgumentException("Parsing of '" + dateString + + "' failed"); + } + + return date; + + } + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java b/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java index fd32cf7ad3..da5292571b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTextualDate.java @@ -12,7 +12,6 @@ import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.FocusEvent; import com.google.gwt.event.dom.client.FocusHandler; -import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.TextBox; import com.vaadin.terminal.gwt.client.ApplicationConnection; @@ -177,44 +176,8 @@ public class VTextualDate extends VDateField implements Paintable, Field, String dateText; Date currentDate = getDate(); if (currentDate != null) { - String formatStr = getFormatString(); - - /* - * Check if format contains the month name. If it does we need to - * 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. - */ - if (formatStr.contains("MMMM")) { - @SuppressWarnings("deprecation") - String monthName = getDateTimeService().getMonth( - currentDate.getMonth()); - - if (monthName != null) { - formatStr = formatStr.replaceAll("[M]{4,}", "'" + monthName - + "'"); - } - } - - if (formatStr.contains("MMM")) { - - @SuppressWarnings("deprecation") - String monthName = getDateTimeService().getShortMonth( - currentDate.getMonth()); - - if (monthName != null) { - formatStr = formatStr.replaceAll("[M]{3,}", "'" + monthName - + "'"); - } - } - - DateTimeFormat format = DateTimeFormat.getFormat(formatStr); - dateText = format.format(currentDate); + dateText = getDateTimeService().formatDate(currentDate, + getFormatString()); } else { dateText = ""; } @@ -243,32 +206,23 @@ public class VTextualDate extends VDateField implements Paintable, Field, public void onChange(ChangeEvent event) { if (!text.getText().equals("")) { try { - DateTimeFormat format = DateTimeFormat - .getFormat(getFormatString()); - Date newDate; + String enteredDate = text.getText(); + + setDate(getDateTimeService().parseDate(enteredDate, + getFormatString(), lenient)); + if (lenient) { - newDate = format.parse(text.getText()); - if (newDate != null) { - // if date value was leniently parsed, normalize text - // presentation - text.setValue( - DateTimeFormat.getFormat(getFormatString()) - .format(newDate), false); - } - } else { - newDate = format.parseStrict(text.getText()); + // If date value was leniently parsed, normalize text + // presentation. + // FIXME: Add a description/example here of when this is + // needed + text.setValue( + getDateTimeService().formatDate(getDate(), + getFormatString()), false); } - long stamp = newDate.getTime(); - if (stamp == 0) { - // If date parsing fails in firefox the stamp will be 0 - setDate(null); - addStyleName(PARSE_ERROR_CLASSNAME); - } else { - setDate(newDate); - // remove possibly added invalid value indication - removeStyleName(PARSE_ERROR_CLASSNAME); - } + // remove possibly added invalid value indication + removeStyleName(PARSE_ERROR_CLASSNAME); } catch (final Exception e) { ClientExceptionHandler.displayError(e.getMessage()); -- cgit v1.2.3