Skip to content

feat: add java.sql.Timestamp converters (#1017) - #1220

Open
Mikkey-f wants to merge 5 commits into
apache:mainfrom
Mikkey-f:feat/1019-timestamp-converters
Open

Mikkey-f wants to merge 5 commits into
apache:mainfrom
Mikkey-f:feat/1019-timestamp-converters

Conversation

@Mikkey-f

@Mikkey-f Mikkey-f commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Purpose of the pull request

Related: #1017 (java.sql.Timestamp slice).

Adds java.sql.Timestamp converter support, carried forward from #1019 by @SyedIshmumAhnaf, who handed the PR over — the original commits are preserved with their authorship and one additional commit brings the code up to date with main.

What's changed?

  • TimestampNumberConverter and TimestampStringConverter (read + write) and TimestampDateConverter (write), registered in DefaultConverterLoader next to the java.sql.Time family.
  • Values keep local date-time semantics on both sides: reads use DateUtils.getLocalDateTime and writes convert through Timestamp#toLocalDateTime(), so no implicit timezone shifts are introduced.

Carry-forward adaptation

  • The 1904 windowing flag now resolves through the shared DateUtils.isDate1904 helper. Reading DateTimeFormatProperty#getUse1904windowing() directly throws a NullPointerException since [Bug] @DateTimeFormat use1904windowing DEFAULT is collapsed to false, bypassing the global 1904 fallback #1042 keeps the annotation DEFAULT as null — any @DateTimeFormat without an explicit use1904windowing value would hit it.
  • Dropped the EasyExcel derived license header from the new files (plain ASF header, written from scratch).
  • Tests moved to converters.timestamp, with qualified assertions and the same thread-local cache teardown as sibling suites, plus a loadConvertersRegistersTimestampFamily case and an XLSX/XLS/CSV round trip.

Review round (2026-10-15)

  • TimestampDateConverter normalises an empty format string to null before WorkBookUtil.fillDataFormat (matching SqlTimeDateConverter) — an empty @DateTimeFormat was previously written through as an empty cell format instead of falling back to the default.
  • TimestampNumberConverter#convertToJavaData returns null when the number is not a valid Excel date (matching SqlTimeNumberConverter) — it previously threw NullPointerException via Timestamp.valueOf(null).

Notes carried over from #1019

  • @nkuprins's review note: the locale test now uses a month name (dd MMMM yyyy HH:mm:ss), so it fails when the locale is not honored.
  • The two Copilot notes (timezone-sensitive write side in the number and date converters) were addressed on the original branch and are preserved here.

Verification

  • Red/green on the adaptation: the new windowing test fails on the original code with NullPointerException: ... because getUse1904windowing() is null, passes after the change.
  • Red/green on the review round: dateConverterFallsBackToDefaultFormatForEmptyDateTimeFormat fails with expected: <yyyy-MM-dd HH:mm:ss> but was: <> and numberConverterReturnsNullForInvalidExcelDate fails with NullPointerException: ... "dateTime" is null; both pass after the change.
  • Full suite: 1061 tests, 0 failures (fesod-common, fesod-shaded, fesod-sheet); spotless:check and javadoc:javadoc pass.

Supersedes #1019 — many thanks to @SyedIshmumAhnaf for the original implementation.

Checklist

  • I have read the Contributor Guide.
  • I have added the necessary unit tests and all cases have passed.

@Mikkey-f Mikkey-f mentioned this pull request Oct 14, 2026
3 tasks done
if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {
format = contentProperty.getDateTimeFormatProperty().getFormat();
}
WorkBookUtil.fillDataFormat(cellData, format, DateUtils.defaultDateFormat);

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.

If format is empty, it is still passed instead of falling back to the default format. Could we normalise an empty format to null?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — fixed in 41ad950: an empty format is now normalised to null before WorkBookUtil.fillDataFormat, matching SqlTimeDateConverter, so it falls back to the default.

Regression test: dateConverterFallsBackToDefaultFormatForEmptyDateTimeFormat — on the old code it fails with expected: <yyyy-MM-dd HH:mm:ss> but was: <>, passes after the change.

@Override
public Timestamp convertToJavaData(
ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return Timestamp.valueOf(DateUtils.getLocalDateTime(

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.

If DateUtils.getLocalDateTime returns null, then it throws. Could we return null in that case for consistency with other converters?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Right — fixed in 41ad950: DateUtils.getLocalDateTime returning null (a number that is not a valid Excel date, e.g. a negative value) no longer reaches Timestamp.valueOf(null); the converter now returns null, mirroring SqlTimeNumberConverter.

Regression test: numberConverterReturnsNullForInvalidExcelDate — red on the old code with NullPointerException: Cannot invoke "java.time.LocalDateTime.getYear()" because "dateTime" is null, green now.

@nkuprins

Copy link
Copy Markdown
Contributor

Please resolve merge conflicts :)

SyedIshmumAhnaf and others added 5 commits October 15, 2026 22:29
Carry-forward of apache#1019 (original implementation by Syed Ishmum Ahnaf):

- Resolve the 1904 windowing flag through the shared DateUtils.isDate1904
  helper, like the rest of the date converter family. Reading
  DateTimeFormatProperty#getUse1904windowing() directly broke on the null
  DEFAULT preserved by apache#1042 and threw a NullPointerException whenever
  @DateTimeFormat was present without an explicit use1904windowing value.
- Drop the EasyExcel derived license header from the four new files; they
  are written from scratch, so the plain ASF header applies.
- Align with current conventions: Class<?> supportJavaTypeKey, single-line
  javadoc, and tests moved to the mirrored converters.timestamp package
  with qualified assertions, the thread-local cache teardown used by the
  sibling suites, a loader family test and an XLSX/XLS/CSV round trip.
@Mikkey-f
Mikkey-f force-pushed the feat/1019-timestamp-converters branch from 715a76d to fe0f779 Compare October 15, 2026 15:21

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

LGTM! Thank you for collaborating with @SyedIshmumAhnaf.

This branch has not been deployed

No deployments
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.

3 participants