diff options
3 files changed, 77 insertions, 1 deletions
diff --git a/client/src/main/java/com/vaadin/client/DateTimeService.java b/client/src/main/java/com/vaadin/client/DateTimeService.java index 00606a25c1..72d51edcae 100644 --- a/client/src/main/java/com/vaadin/client/DateTimeService.java +++ b/client/src/main/java/com/vaadin/client/DateTimeService.java @@ -39,6 +39,10 @@ public class DateTimeService { private static int[] maxDaysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + private int[] yearDays = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, + 304, 334 }; + private int[] leapYearDays = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, + 305, 335}; private static final long MILLISECONDS_PER_DAY = 24 * 3600 * 1000; @@ -373,6 +377,10 @@ public class DateTimeService { */ public String formatDate(Date date, String formatStr, TimeZone timeZone) { /* + * Format week numbers + */ + formatStr = formatWeekNumbers(date, formatStr); + /* * Format month and day names separately when locale for the * DateTimeService is not the same as the browser locale */ @@ -388,6 +396,47 @@ public class DateTimeService { return result; } + /* + * Calculate number of the week in the year based on Date + * Note, support for "ww" is missing GWT DateTimeFormat + * and java.util.Calendar is not supported in GWT + * Hence DIY method needed + */ + private String getWeek(Date date) { + int year = date.getYear()+1900; + int month = date.getMonth(); + int day = date.getDate()+1; + int weekDay = date.getDay(); + if (weekDay == 6) { + weekDay = 0; + } else { + weekDay = weekDay - 1; + } + boolean leap = false; + if (((year % 4) == 0) && (((year % 100) != 0) || ((year % 400) == 0))) { + leap = true; + } + int week; + if (leap) { + week = countWeek(leapYearDays, month, day, weekDay); + } else { + week = countWeek(yearDays, month, day, weekDay); + } + return ""+week; + } + + private int countWeek(int[] days, int month, int day, int weekDay) { + return ((days[month] + day) - (weekDay + 7) % 7 + 7) / 7; + } + + private String formatWeekNumbers(Date date, String formatStr) { + if (formatStr.contains("ww")) { + String weekNumber = getWeek(date); + formatStr = formatStr.replaceAll("ww", weekNumber); + } + return formatStr; + } + private String formatDayNames(Date date, String formatStr) { if (formatStr.contains("EEEE")) { String dayName = getDay(date.getDay()); diff --git a/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java b/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java index 7bd245382f..9314f5d9b9 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java +++ b/server/src/main/java/com/vaadin/ui/AbstractLocalDateField.java @@ -15,9 +15,11 @@ */ package com.vaadin.ui; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.time.Instant; import java.time.LocalDate; -import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; @@ -26,6 +28,7 @@ import java.util.Date; import java.util.Locale; import java.util.Map; +import com.vaadin.data.Result; import com.vaadin.data.validator.DateRangeValidator; import com.vaadin.data.validator.RangeValidator; import com.vaadin.shared.ui.datefield.AbstractTextualDateFieldState; @@ -163,4 +166,27 @@ public abstract class AbstractLocalDateField return temporalAccessor == null ? null : LocalDate.from(temporalAccessor); } + + @Override + protected Result<LocalDate> handleUnparsableDateString(String dateString) { + // Handle possible week number, which cannot be parsed client side due + // limitations in GWT + if (this.getDateFormat() != null && this.getDateFormat().contains("w")) { + Date parsedDate; + SimpleDateFormat df = new SimpleDateFormat(this.getDateFormat(),this.getLocale()); + try { + parsedDate = df.parse(dateString); + } catch (ParseException e) { + return super.handleUnparsableDateString(dateString); + } + ZoneId zi = this.getZoneId(); + if (zi == null) { + zi = ZoneId.systemDefault(); + } + LocalDate date = Instant.ofEpochMilli(parsedDate.getTime()).atZone(zi).toLocalDate(); + return Result.ok(date); + } else { + return super.handleUnparsableDateString(dateString); + } + } } diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/AbstractDateFieldTest.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/AbstractDateFieldTest.java index 9d7d75efb8..3a5e57273c 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/AbstractDateFieldTest.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/AbstractDateFieldTest.java @@ -64,6 +64,7 @@ public abstract class AbstractDateFieldTest<T extends AbstractLocalDateField> getDatePattern(new Locale("fi", "FI"), DateFormat.MEDIUM)); options.put(getDatePattern(new Locale("fi", "FI"), DateFormat.SHORT), getDatePattern(new Locale("fi", "FI"), DateFormat.SHORT)); + options.put("ww yyyy", "ww yyyy"); createSelectAction("Date format", category, options, "-", dateFormatCommand); |