Skip to content

WW-5810 Support java.time types in the datetextfield tag - #2056

Merged
lukaszlenart merged 2 commits into
mainfrom
WW-5810-datetextfield-java-time
Oct 24, 2026
Merged

lukaszlenart merged 2 commits into
mainfrom
WW-5810-datetextfield-java-time

Conversation

@lukaszlenart

Copy link
Copy Markdown
Member

Fixes WW-5810

What

datetextfield now works with java.time properties in both the html5 theme and the JavaTemplates plugin.

  • DateConverter converts a java.util.Date object into LocalDate, LocalDateTime or LocalTime in the server's default time zone. Before, it returned the Date unchanged whatever the target type, so a java.time property could not bind. This is the value DateTextFieldInterceptor binds, so the interceptor itself is unchanged. Date targets keep the existing behaviour. The instant is read via getTime(), because java.sql.Date.toInstant() throws.
  • JavaTemplates DateTextFieldHandler no longer casts nameValue to Date (a ClassCastException for any java.time value). It formats java.time values per field with DateTimeFormatter; a field the type does not have, such as HH on a LocalDate, renders empty.
  • html5 theme: LocalDate already rendered as ISO through toString(); now pinned by a test. A value with a time part (LocalDateTime, ZonedDateTime, OffsetDateTime) renders its date part instead of 2026-10-24T10:15, which the browser rejects and shows as an empty field.

Scope decisions

  • JavaTemplates supports LocalDate, LocalDateTime and LocalTime, the three DateConverter already accepts from strings. ZonedDateTime/OffsetDateTime are out: a split-field form has no zone or offset to submit.
  • html5 supports LocalDate. Binding a date-only input back into a time-bearing property still fails conversion; the docs point to textfield type="datetime-local" for those.
  • Binding is fixed in the converter rather than by making the interceptor emit an ISO string, so existing Date bindings don't move onto the string-parsing path (see WW-5812).

Tests

  • DateConverterTest: Date and java.sql.Date into each java.time type; Date → Date unchanged.
  • DateTextFieldInterceptorTest#testBindsToALocalDateProperty: split fields → interceptor → value stack → LocalDate property.
  • html5 DateTextFieldTest: LocalDate as ISO, date part of a LocalDateTime.
  • JavaTemplates DateTextFieldTest: Date, LocalDate, LocalDateTime, LocalTime, and an empty time field on a LocalDate.
  • Full suites green: core 3561, JavaTemplates 88.

Site docs: apache/struts-site PR to follow.

🤖 Generated with Claude Code

DateConverter now converts a java.util.Date object into LocalDate,
LocalDateTime or LocalTime in the server's default time zone. That is
the value DateTextFieldInterceptor binds, so the JavaTemplates split
fields can now fill java.time properties; Date targets are unchanged.

The JavaTemplates handler formats java.time values per field instead of
casting to Date, leaving a field the type does not have empty. The html5
theme renders the date part of a time-bearing value, which the browser
otherwise rejects; LocalDate already rendered as ISO and is now pinned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Split-field rendering and parsing use incompatible calendars under the Thai default locale, causing unchanged form submissions to bind a different date.

1 open issue
What changed in this PR

Adds java.time support to Struts datetextfield rendering and split-field binding while preserving existing Date behavior.

Changes:

  • Converts Date objects into LocalDate, LocalDateTime, and LocalTime.
  • Formats temporal values in JavaTemplates and extracts ISO dates for HTML5 inputs.
  • Adds converter, binding, and rendering regression tests.
File Description
plugins/​javatemplates/​src/​test/​java/​org/​apache/​struts2/​views/​java/​simple/​DateTextFieldTest.java Tests legacy and temporal split-field rendering.
plugins/​javatemplates/​src/​main/​java/​org/​apache/​struts2/​views/​java/​simple/​DateTextFieldHandler.java Formats temporal values without casting to Date.
core/​src/​test/​resources/​org/​apache/​struts2/​views/​jsp/​ui/​DateTextField-6-html5.txt Expected date-only output for LocalDateTime.
core/​src/​test/​resources/​org/​apache/​struts2/​views/​jsp/​ui/​DateTextField-5-html5.txt Expected ISO output for LocalDate.
core/​src/​test/​java/​org/​apache/​struts2/​views/​jsp/​ui/​DateTextFieldTest.java Tests HTML5 temporal rendering.
core/​src/​test/​java/​org/​apache/​struts2/​interceptor/​DateTextFieldInterceptorTest.java Tests split-field binding to LocalDate.
core/​src/​test/​java/​org/​apache/​struts2/​conversion/​impl/​DateConverterTest.java Tests object conversion and unchanged Date handling.
core/​src/​test/​java/​org/​apache/​struts2/​components/​ConstraintAction.java Adds temporal properties for rendering tests.
core/​src/​main/​java/​org/​apache/​struts2/​conversion/​impl/​DateConverter.java Converts legacy dates to local temporal types.
core/​src/​main/​java/​org/​apache/​struts2/​components/​DateTextField.java Supplies ISO dates for date-bearing temporal values.

Review effort: Balanced

…endar

DateTimeFormatter always uses the ISO calendar, while
DateTextFieldInterceptor parses with SimpleDateFormat, which follows the
default locale's calendar. Under th-TH a LocalDate of 2026-10-24
rendered year 2026 and bound back as 1483-11-02. java.time values are
now converted to a Date and formatted with SimpleDateFormat like the
Date path; a field the type does not have still renders empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@lukaszlenart
lukaszlenart merged commit 53eb6f7 into main Oct 24, 2026
7 checks passed
@lukaszlenart
lukaszlenart deleted the WW-5810-datetextfield-java-time branch October 24, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants