[ 
https://issues.apache.org/jira/browse/WW-5814?focusedWorklogId=1049996&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1049996
 ]

ASF GitHub Bot logged work on WW-5814:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 25/Oct/26 06:33
            Start Date: 25/Oct/26 06:33
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart opened a new pull request, #2059:
URL: https://github.com/apache/struts/pull/2059

   Fixes [WW-5814](https://issues.apache.org/jira/browse/WW-5814)
   
   ## Problem
   
   `DateConverter` accepts ISO date-times ending in `Z` for `java.util.Date` 
properties (since WW-5813 through explicit `'Z'`-literal formats), but treats 
the `Z` as a literal. `2026-10-25T05:14:42.000Z`, the form JavaScript's 
`Date.toISOString()` produces, is read in the server's default time zone, so a 
UTC timestamp from a client is shifted by the server's offset. Numeric offsets 
(`+02:00`) are rejected.
   
   ## Change
   
   Reading `Z` as UTC changes the instant every existing `...Z` value converts 
to, silently and with no conversion error, so it is opt-in:
   
   - new constant `struts.converter.date.isoOffsetAware` 
(`StrutsConstants.STRUTS_CONVERTER_DATE_ISO_OFFSET_AWARE`), default `false` in 
`default.properties`
   - `false`: unchanged, `Z` read as server-local time
   - `true`: a `java.util.Date` target (and `Calendar`, which converts through 
it) first tries `DateTimeFormatter.ISO_OFFSET_DATE_TIME`:
     - `Z` means UTC
     - numeric offsets are honoured
     - 0-9 fractional digits are read as a fraction (with the flag off, `.5Z` 
reads as 5 ms, because `.SSS` counts digits)
   - input without an offset falls through to the existing formats unchanged
   - a year outside `Date`'s range is a conversion error instead of an escaping 
`IllegalArgumentException`
   
   The default flips to `true` in 8.0.0: 
[WW-5815](https://issues.apache.org/jira/browse/WW-5815).
   
   Out of scope:
   
   - `java.sql.Timestamp`, which has no ISO support today
   - the `java.time` types: `OffsetDateTime` already parses offsets, and the 
`Local*` types have no zone
   - the JSON plugin's own date handling
   
   ## Tests
   
   - Off by default, using the container's `DateConverter`.
   - Setting the constant through `initDispatcher` turns the reading on.
   - With the flag on:
     - `Z` with and without milliseconds is read as UTC
     - `+02:00` is honoured
     - `.5` reads as half a second
     - input without an offset keeps the local reading
     - an out-of-range year is rejected
   - The `Z` tests pin `Asia/Tokyo` as the default zone and restore it in 
`tearDown`, so they cannot pass vacuously on a UTC build machine.
   - Each test was seen failing first. The range check was also confirmed by 
removing it.
   - Full core suite on JDK 17 and JDK 25, plus the spring, junit, 
javatemplates and json plugins on JDK 17, all green.
   
   ## Docs
   
   - 7.5.0 release notes: the new constant.
   - struts-site: the constant needs a line on the configuration page.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   




Issue Time Tracking
-------------------

            Worklog Id:     (was: 1049996)
    Remaining Estimate: 0h
            Time Spent: 10m

> DateConverter reads a trailing Z in an ISO date-time as server-local time 
> instead of UTC
> ----------------------------------------------------------------------------------------
>
>                 Key: WW-5814
>                 URL: https://issues.apache.org/jira/browse/WW-5814
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core
>            Reporter: Lukasz Lenart
>            Assignee: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.5.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> {{DateConverter}} accepts ISO date-times such as {{1996-12-19T16:39:57Z}} and 
> {{2026-10-25T05:14:42.000Z}} (the form JavaScript's {{Date.toISOString()}} 
> produces) for {{java.util.Date}} properties, but treats the {{Z}} as a 
> literal. The value is interpreted in the server's default time zone, so a UTC 
> timestamp sent by a client is shifted by the server's offset.
> Other RFC 3339 forms are not accepted at all: a numeric offset ({{+02:00}}), 
> and fractional seconds with other than three digits.
> h2. Background
> Before WW-5813 the converter ignored any text after 
> {{yyyy-MM-dd'T'HH:mm:ss}}, so {{Z}} and {{.SSSZ}} were silently dropped. 
> WW-5813 rejects trailing text, and keeps these two inputs working by adding 
> {{yyyy-MM-dd'T'HH:mm:ss'Z'}} and {{yyyy-MM-dd'T'HH:mm:ss.SSS'Z'}} formats 
> that preserve the previous local-time reading. 
> {{OgnlUtilTest.testSetPropertiesDate}} pins that reading.
> h2. Fix
> Reading {{Z}} as UTC changes the instant every existing {{...Z}} value 
> converts to (shifted by the server's offset), silently and without a 
> conversion error, so it goes behind an opt-in flag:
> * new constant {{struts.converter.date.isoOffsetAware}}, default {{false}}
> * {{false}}: behaviour as released after WW-5813, {{Z}} read as server-local 
> time
> * {{true}}: for {{java.util.Date}} (and {{Calendar}}, which goes through it) 
> an ISO date-time with an offset is parsed with 
> {{DateTimeFormatter.ISO_OFFSET_DATE_TIME}}, so {{Z}} means UTC, numeric 
> offsets are honoured and 0-9 fractional digits are accepted
> {{java.sql.Timestamp}} (no ISO support today), the {{java.time}} types 
> ({{OffsetDateTime}} already parses offsets) and the JSON plugin's own date 
> handling are out of scope.
> The default flips to {{true}} in 8.0.0 under a separate ticket.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to