Skip to content

fix: support negative year (BC date) deserialization#4036

Open
daguimu wants to merge 1 commit intoalibaba:mainfrom
daguimu:fix/negative-year-datetime-issue3845
Open

fix: support negative year (BC date) deserialization#4036
daguimu wants to merge 1 commit intoalibaba:mainfrom
daguimu:fix/negative-year-datetime-issue3845

Conversation

@daguimu
Copy link
Copy Markdown

@daguimu daguimu commented Mar 25, 2026

Problem

LocalDateTime with negative years (BC dates) serializes correctly (e.g. "-0001-12-31 16:00:00") but fails to deserialize with:

JSONException: read LocalDateTime error -0001-12-31 16:00:00

Reproduction:

LocalDateTime time = LocalDateTime.of(0, 1, 1, 0, 0, 0, 0).minusHours(8);
JSONObject bean = new JSONObject().fluentPut("time", time);
String s = bean.toJSONString();  // {"time":"-0001-12-31 16:00:00"}
JSON.parseObject(s).getLocalDateTime("time");  // throws JSONException

Root Cause

The negative year date string "-0001-12-31 16:00:00" has length 20 (due to the leading -). The readLocalDateTime() method dispatches length-20 strings to parseLocalDateTime20(), which expects a completely different format (dd Mon yyyy HH:mm:ss). This returns null, and the string eventually falls through to an error.

Fix

Added handling for the -yyyy-MM-dd HH:mm:ss format in the string fallback path of readLocalDateTime(). The fix:

  • Checks if the string is 20 chars starting with -
  • Validates the format matches -yyyy-MM-dd HH:mm:ss (supporting both and T separators, and / delimiters)
  • Manually parses the year, month, day, hour, minute, second components
  • Follows the same manual parsing style used throughout the codebase

Tests Added

  • testNegativeYearRoundTrip — Serialize then deserialize a BC date, verify equality
  • testNegativeYearDirectParse — Parse "-0001-12-31 16:00:00" and verify all components
  • testNegativeYearWithT — Parse with T separator: "-0001-12-31T16:00:00"
  • testNegativeYearWithSlash — Parse with / delimiter: "-0001/12/31 16:00:00"
  • testNegativeYearLarger — Year -100 (101 BC) round-trip
  • testPositiveYearStillWorks — Regression test for normal dates

Impact

Minimal — only affects deserialization of negative year datetime strings (20 chars starting with -). Normal date parsing is unaffected.

Fixes #3845

…Time

LocalDateTime with negative years (e.g. year -1 = 2 BC) serializes as
"-0001-12-31 16:00:00" (20 chars). The readLocalDateTime method dispatched
this to parseLocalDateTime20 which expects a different date format,
causing it to fail with "read LocalDateTime error".

Add handling for the -yyyy-MM-dd HH:mm:ss format in the string fallback
path, supporting both space and T separators, and / delimiters.

Fixes alibaba#3845
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.

[BUG]公元前时间反序列化出错

1 participant