Repository: primefaces/primefaces (java)

Issue:
DatePicker: posting week selection doesnt work
Week Picker: '3/22/2025 (Wk 12)' could not be understood as a date.
Week Picker: '3/22/2025 (Wk 12)' could not be understood as a date. Example: 3/15/2025


Either we need to introduce a hidden input like in other components or just remove everything after the rangeSeparator on server side.

WDYT @melloware?

Pull request description:
Fixes #13566 - DatePicker: posting week selection doesnt work 
Fixes #13566

Patch:
diff --git a/primefaces-showcase/src/main/java/org/primefaces/showcase/view/input/CalendarJava8View.java b/primefaces-showcase/src/main/java/org/primefaces/showcase/view/input/CalendarJava8View.java
index 7ede301165..5df7f7ffea 100644
--- a/primefaces-showcase/src/main/java/org/primefaces/showcase/view/input/CalendarJava8View.java
+++ b/primefaces-showcase/src/main/java/org/primefaces/showcase/view/input/CalendarJava8View.java
@@ -139,6 +139,15 @@ public class CalendarJava8View implements Serializable {
         facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Date Selected", event.getObject().format(formatter)));
     }
 
+    public void onDateRangeSelect(SelectEvent<List<LocalDate>> event) {
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
+        String range = event.getObject().get(0).format(formatter)
+                + " - "
+                + event.getObject().get(event.getObject().size() - 1).format(formatter);
+        facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Range Selected", range));
+    }
+
     public void onDateTimeSelect(SelectEvent<LocalDateTime> event) {
         FacesContext facesContext = FacesContext.getCurrentInstance();
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
diff --git a/primefaces-showcase/src/main/webapp/ui/input/datepicker/datePickerJava8.xhtml b/primefaces-showcase/src/main/webapp/ui/input/datepicker/datePickerJava8.xhtml
index 4d7becb426..68c23ed3c8 100644
--- a/primefaces-showcase/src/main/webapp/ui/input/datepicker/datePickerJava8.xhtml
+++ b/primefaces-showcase/src/main/webapp/ui/input/datepicker/datePickerJava8.xhtml
@@ -70,7 +70,9 @@
 
                     <div class="field col-12 md:col-4">
                         <p:outputLabel for="@next" value="Week Picker" />
-                        <p:datePicker id="week" view="week" value="#{calendarJava8View.week}" />
+                        <p:datePicker id="week" view="week" value="#{calendarJava8View.week}">
+                            <p:ajax event="dateSelect" listener="#{calendarJava8View.onDateRangeSelect}" update="msgs" />
+                        </p:datePicker>
                     </div>
 
                     <div class="field col-12 md:col-4">
diff --git a/primefaces/src/main/java/org/primefaces/component/datepicker/DatePickerRenderer.java b/primefaces/src/main/java/org/primefaces/component/datepicker/DatePickerRenderer.java
index 93e1af0b4d..536a3d49ec 100644
--- a/primefaces/src/main/java/org/primefaces/component/datepicker/DatePickerRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/datepicker/DatePickerRenderer.java
@@ -371,7 +371,8 @@ public class DatePickerRenderer extends BaseCalendarRenderer<DatePicker> {
 
                 return multi;
             case "range":
-                List<String> rangeStr = CalendarUtils.splitRange(submittedValue, datePicker.calculatePattern(), datePicker.getRangeSeparator());
+                List<String> rangeStr = CalendarUtils.splitRange(submittedValue, datePicker.calculatePattern(),
+                        datePicker.getRangeSeparator(), "week".equals(datePicker.getView()));
                 List<Object> range = new ArrayList<>();
                 if (rangeStr.size() == 2) {
                     for (int i = 0; i < rangeStr.size(); i++) {
diff --git a/primefaces/src/main/java/org/primefaces/util/CalendarUtils.java b/primefaces/src/main/java/org/primefaces/util/CalendarUtils.java
index d7c3943bda..a8bfed15c6 100644
--- a/primefaces/src/main/java/org/primefaces/util/CalendarUtils.java
+++ b/primefaces/src/main/java/org/primefaces/util/CalendarUtils.java
@@ -41,7 +41,8 @@ import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.time.temporal.Temporal;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
@@ -637,19 +638,30 @@ public class CalendarUtils {
         return now;
     }
 
-    public static List<String> splitRange(final String dateRange, final String pattern, final String separator) {
-        final String token = Constants.SPACE + separator + Constants.SPACE;
-        if (pattern.contains(token)) {
-            throw new FacesException("Pattern '" + pattern + "' contains separator '" + token + "'");
+    public static List<String> splitRange(String input, String datePattern, String rangeSeparator,
+                                          boolean week) {
+
+        // security check
+        String token = Constants.SPACE + rangeSeparator + Constants.SPACE;
+        if (datePattern.contains(token)) {
+            throw new FacesException("Pattern '" + datePattern + "' contains separator '" + token + "'");
         }
-        final List<String> dates = new ArrayList<>();
-        if (!dateRange.contains(token)) {
-            return dates;
+
+        // fast return
+        if (!input.contains(token)) {
+            return Collections.emptyList();
         }
-        final int index = dateRange.indexOf(token);
-        dates.add(dateRange.substring(0, index));
-        dates.add(dateRange.substring(index + token.length()));
-        return dates;
+
+        int tokenIndex = input.indexOf(token);
+        String from = input.substring(0, tokenIndex);
+        String to = input.substring(tokenIndex + token.length());
+        if (week) {
+            // hardcoded pattern, see JS:
+            // formattedValue += ' (' + this.options.locale.weekHeader + ' ' + week + ')';
+            to = to.substring(0, to.lastIndexOf(" ("));
+        }
+
+        return Arrays.asList(from, to);
     }
 
 }


Test patch:
diff --git a/primefaces/src/test/java/org/primefaces/util/CalendarUtilsTest.java b/primefaces/src/test/java/org/primefaces/util/CalendarUtilsTest.java
index 44e088c1d0..401933b6c8 100644
--- a/primefaces/src/test/java/org/primefaces/util/CalendarUtilsTest.java
+++ b/primefaces/src/test/java/org/primefaces/util/CalendarUtilsTest.java
@@ -217,18 +217,33 @@ class CalendarUtilsTest {
 
     @Test
     void splitRange() {
-        List<String> splitRange = CalendarUtils.splitRange("2021-03-01 - 2021-03-31", "yyyy-MM-dd", "-");
+        List<String> splitRange = CalendarUtils.splitRange("2021-03-01 - 2021-03-31", "yyyy-MM-dd", "-", false);
         assertEquals(2, splitRange.size());
         assertEquals("2021-03-01", splitRange.get(0));
         assertEquals("2021-03-31", splitRange.get(1));
-        splitRange = CalendarUtils.splitRange("2021-03-01", "yyyy-MM-dd", "-");
+        splitRange = CalendarUtils.splitRange("2021-03-01", "yyyy-MM-dd", "-", false);
         assertTrue(splitRange.isEmpty());
-        splitRange = CalendarUtils.splitRange("", "yyyy-MM-dd", "-");
+        splitRange = CalendarUtils.splitRange("", "yyyy-MM-dd", "-", false);
         assertTrue(splitRange.isEmpty());
 
         assertThrows(FacesException.class, () -> {
-            CalendarUtils.splitRange("2021 - 03 - 01 - 2021 - 03 - 31", "yyyy - MM - dd", "-");
+            CalendarUtils.splitRange("2021 - 03 - 01 - 2021 - 03 - 31", "yyyy - MM - dd", "-", false);
         });
     }
 
+    @Test
+    void splitRangeWeek() {
+        List<String> splitRange = CalendarUtils.splitRange("2021-03-01 - 2021-03-31 (Wk 21)", "yyyy-MM-dd", "-", true);
+        assertEquals(2, splitRange.size());
+        assertEquals("2021-03-01", splitRange.get(0));
+        assertEquals("2021-03-31", splitRange.get(1));
+        splitRange = CalendarUtils.splitRange("2021-03-01 (Wk 21)", "yyyy-MM-dd", "-", true);
+        assertTrue(splitRange.isEmpty());
+        splitRange = CalendarUtils.splitRange("", "yyyy-MM-dd (Wk 21)", "-", true);
+        assertTrue(splitRange.isEmpty());
+
+        assertThrows(FacesException.class, () -> {
+            CalendarUtils.splitRange("2021 - 03 - 01 - 2021 - 03 - 31 (Wk 21)", "yyyy - MM - dd", "-", true);
+        });
+    }
 }