Skip to content

[2.x] Validate RFC 3339 fractional seconds in time format - #1315

Merged
stevehu merged 1 commit into
networknt:2.xfrom
MoChiUaena:codex/fix-time-fraction-rfc3339-2x
Oct 13, 2026
Merged

stevehu merged 1 commit into
networknt:2.xfrom
MoChiUaena:codex/fix-time-fraction-rfc3339-2x

Conversation

@MoChiUaena

Copy link
Copy Markdown
Contributor

The time format accepts 12:00:00.Z but rejects 12:00:00.1234567890Z on the 2.x branch. RFC 3339 requires at least one digit after . and permits more than nine digits.

Check the fraction before parsing and shorten only the validation copy to nine digits, which is Java's parser limit. The existing offset, range, and leap-second checks remain in place. Added regression cases for empty fractions, longer fractions, and malformed trailing text.

Tested with mvn clean verify on JDK 8, 11, 17, and 21 (8,673 tests, 0 failures or errors, 15 skipped on each).

Related to #1311.

Signed-off-by: dlwlrma <965810157@qq.com>

@stevehu stevehu 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.

Thanks, this looks good. I reviewed #1314 and #1315 together; the changes are identical on both branches.

Verification

  • #1315 on 2.x (Java 8, 11, 21) and #1314 on master (JDK 17, 25): TimeFormatTest (29), the JSON Schema Test Suite (7261), the extras and the format tests pass.
  • Revert check: with the base TimeFormat, 7 of the new tests fail: the 4 empty-fraction cases and the 3 ten-digit cases.
  • 400k generated inputs compared against an RFC 3339 reference: 0 mismatches on all five JDKs. Before this change, these fraction cases were the only mismatches.
  • 29 adversarial inputs aimed at the rewrite all matched the reference on Java 8 and JDK 25. They cover dots in odd places, several dots, trailing text after a long fraction, the Java 8 +HH:MM:SS offset after a long fraction, and leap seconds with long fractions. A 1M-digit fraction takes about 1 ms.

Optional, not blocking

  • Since matches() never reads NANO_OF_SECOND, the rewrite could drop the fraction entirely (value.substring(0, decimalPoint) + value.substring(fractionEnd)) instead of keeping 9 digits.
  • Tests worth adding: 12:00:00.1234567890Zjunk and 12:00:00.1234567890+01:00:00 as invalid, and a ~100-digit fraction as valid. These are the paths where parsedValue and value differ.
  • The date-time side of #1311 (more than 9 digits rejected; empty fraction accepted by the java.time fallback) is now tracked in #1316.

Approving. We'll merge #1314 and #1315 together once CI passes.

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