You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "ASF GitHub Bot (Jira)" <ji...@apache.org> on 2026/09/13 10:27:00 UTC
[jira] [Work logged] (WW-5686) renders a java.sql.Date with the current wall-clock time, making DateTest.testJavaSqlDate flaky
[ https://issues.apache.org/jira/browse/WW-5686?focusedWorklogId=1041193&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1041193 ]
ASF GitHub Bot logged work on WW-5686:
--------------------------------------
Author: ASF GitHub Bot
Created on: 13/Sep/26 10:26
Start Date: 13/Sep/26 10:26
Worklog Time Spent: 10m
Work Description: lukaszlenart opened a new pull request, #1929:
URL: https://github.com/apache/struts/pull/1929
Fixes [WW-5686](https://issues.apache.org/jira/browse/WW-5686)
`Date.end` completes a `java.sql.Date` with `LocalTime.now(tz)`, while `testJavaSqlDate` built its expected string from a `java.sql.Date` captured moments earlier. The two disagree whenever the wall clock crosses a second boundary, which is how the test went red on the SonarCloud job of #1859 (an unrelated OGNL change).
The test now uses a fixed `java.sql.Date.valueOf("2024-03-15")` and a date-only `yyyy-MM-dd` format, the same approach `testJavaSqlTime` already takes: it asserts the part of the output the value actually determines and no longer depends on the clock. Proven non-vacuous by temporarily adding `plusDays(1)` to the `java.sql.Date` branch — `expected:<2024-03-1[5]> but was:<2024-03-1[6]>`.
`Date.java` is unchanged. Completing a `java.sql.Date` at start of day (the pre-6.2.0 behaviour) alters observable output for time-bearing formats, so it is tracked separately as [WW-5738](https://issues.apache.org/jira/browse/WW-5738) at 8.0.0.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Issue Time Tracking
-------------------
Worklog Id: (was: 1041193)
Remaining Estimate: 0h
Time Spent: 10m
> <s:date/> renders a java.sql.Date with the current wall-clock time, making DateTest.testJavaSqlDate flaky
> ---------------------------------------------------------------------------------------------------------
>
> Key: WW-5686
> URL: https://issues.apache.org/jira/browse/WW-5686
> Project: Struts 2
> Issue Type: Bug
> Components: Core Tags, Unit Tests
> Reporter: Lukasz Lenart
> Assignee: Lukasz Lenart
> Priority: Minor
> Fix For: 7.4.0
>
> Time Spent: 10m
> Remaining Estimate: 0h
>
> {{org.apache.struts2.components.Date.end}} fills in the missing time-of-day of a {{java.sql.Date}} from the current clock:
> {code:java}Object dateObject = findValue(name);
> if (dateObject instanceof java.sql.Date) {
> date = ((java.sql.Date) dateObject).toLocalDate().atTime(LocalTime.now(tz)).atZone(tz);
> } else if (dateObject instanceof java.sql.Time) {
> date = ((java.sql.Time) dateObject).toLocalTime().atDate(ZonedDateTime.now(tz).toLocalDate()).atZone(tz);
> }
> {code}
> Two consequences.
> h3. 1. The rendered output is non-deterministic
> A {{java.sql.Date}} carries no time-of-day, so any format that includes time fields renders whatever the wall clock happens to say at render time. The same value rendered twice in one page produces two different strings.
> This was not always the behaviour. WW-5197 (6.0.3) added {{java.sql.Date}} support as {{toLocalDate().atStartOfDay(tz)}} — deterministic midnight. WW-5272 (commit {{08de24588}}, 6.2.0, "Extends <s:date/> to support java.sql.Time") changed it to {{atTime(LocalTime.now(tz))}} while adding the {{java.sql.Time}} branch, and changed {{DateTest}} in the same commit from {{getDateInstance(MEDIUM)}} to {{getDateTimeInstance(MEDIUM, MEDIUM)}} so the assertion would cover the newly rendered time. The {{java.sql.Time}} branch genuinely needs a date to complete a {{ZonedDateTime}}, but the {{java.sql.Date}} branch has no equivalent need for _now's_ time — midnight completed it just as well, and did so reproducibly. This looks like collateral of the {{java.sql.Time}} work rather than an intended change to {{java.sql.Date}} rendering, and it shipped without a note.
> h3. 2. {{DateTest.testJavaSqlDate}} is inherently flaky
> The test builds its expected string from {{new java.sql.Date(System.currentTimeMillis())}}, whose underlying millis still carry the capture-time time-of-day, and compares it against output whose time comes from {{LocalTime.now()}} at render. The two disagree whenever the clock crosses a second boundary between the two calls.
> Observed on the SonarCloud job of [PR #1859|https://github.com/apache/struts/pull/1859] (an unrelated OGNL change):
> {code}DateTest.testJavaSqlDate:104 expected:<Aug 23, 2026, 4:37:1[4] PM> but was:<Aug 23, 2026, 4:37:1[5] PM>
> {code}
> The same commit passed Build and Test on JDK 17, 21 and 25 — only that one job happened to straddle the boundary. The failure window is roughly the elapsed time between the two calls, so it is rare but will keep failing unrelated PRs.
> {{testJavaSqlTime}} is not affected in practice: it formats with {{hh:mm:ss}}, and {{toLocalTime()}} preserves the value's own time, so the substituted date is never rendered. It would only misfire across a midnight boundary.
> h3. Suggested fix
> Restore {{toLocalDate().atStartOfDay(tz)}} for {{java.sql.Date}} and assert against a fixed instant in the test rather than the current time. That reverts {{java.sql.Date}} rendering to its pre-6.2.0 semantics, so it needs a Version Notes entry.
> If the current behaviour is instead considered intentional, the test still has to stop racing the clock — inject a fixed clock or assert only the date fields — and the substitution should be documented on the tag.
> _Affects:_ 6.2.0 onwards, on every maintained line.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)