Skip to content

Fix Date fields in complex types returning epoch day integers#1248

Merged
vikrantpuppala merged 3 commits intodatabricks:mainfrom
vikrantpuppala:fix/1247-date-epoch-day-in-complex-types
Mar 9, 2026
Merged

Fix Date fields in complex types returning epoch day integers#1248
vikrantpuppala merged 3 commits intodatabricks:mainfrom
vikrantpuppala:fix/1247-date-epoch-day-in-complex-types

Conversation

@vikrantpuppala
Copy link
Collaborator

@vikrantpuppala vikrantpuppala commented Mar 4, 2026

Summary

  • Fixes [BUG] Date fields within ARRAY<STRUCT> types are serialized as Epoch Days (integers) rather than ISO-8601 strings. #1247: Date fields within ARRAY<STRUCT>, ARRAY<DATE>, MAP<*,DATE>, and other complex types were serialized as epoch day integers instead of proper java.sql.Date objects.
  • Arrow's getObject() on nested types returns epoch day integers for DATE fields. ComplexDataTypeParser.convertPrimitive() now falls back to parsing epoch day integers via LocalDate.ofEpochDay() when Date.valueOf() fails on non-ISO-8601 input.
  • Non-numeric invalid date strings preserve the original IllegalArgumentException.

Test plan

  • testDateAsEpochDayInStruct — verifies DATE epoch day integers in ARRAY<STRUCT<event_date:DATE>>
  • testDateAsEpochDayInArray — verifies DATE epoch day integers in ARRAY<DATE>
  • testDateAsEpochDayInMap — verifies DATE epoch day integers in MAP<STRING,DATE>
  • testDateAsStringInStruct — verifies ISO-8601 date strings still work (no regression)
  • testInvalidDateStringInStructThrowsOriginalException — verifies error behavior for invalid strings
  • All 18 ComplexDataTypeParserTest tests pass

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings March 4, 2026 05:07
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes incorrect DATE handling inside nested/complex types where Arrow can surface DATEs as epoch-day integers, ensuring parsed results become proper java.sql.Date objects instead of numeric day counts.

Changes:

  • Added DATE parsing fallback to interpret non-ISO DATE inputs as epoch-day integers via LocalDate.ofEpochDay(...).
  • Added regression tests covering DATE epoch-day integers in ARRAY<STRUCT<...>>, ARRAY<DATE>, and MAP<*,DATE>, plus a non-regression test for ISO-8601 date strings.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/main/java/com/databricks/jdbc/api/impl/ComplexDataTypeParser.java Adds epoch-day integer fallback when DATE parsing via Date.valueOf(String) fails.
src/test/java/com/databricks/jdbc/api/impl/ComplexDataTypeParserTest.java Adds tests validating epoch-day DATE handling across nested ARRAY/STRUCT/MAP scenarios.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Collaborator

@sreekanth-db sreekanth-db left a comment

Choose a reason for hiding this comment

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

Should we handle this for DatabricksTypeUtil.TIME as well ?
(please consider timezone complexities as well if we plan to support this)

@vikrantpuppala
Copy link
Collaborator Author

@sreekanth-db see #1250

Copy link
Collaborator

@madhav-db madhav-db left a comment

Choose a reason for hiding this comment

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

LGTM, minor nit

// Arrow serializes DATE fields in nested types as epoch day integers.
// Fall back to parsing as epoch day count (days since 1970-01-01).
try {
return Date.valueOf(LocalDate.ofEpochDay(Long.parseLong(text)));
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Should catch a DateTimeException here too, in case Long.parseLong returns an out-of-range value for LocalDate

try {
return Date.valueOf(LocalDate.ofEpochDay(Long.parseLong(text)));
} catch (NumberFormatException nfe) {
throw e;
Copy link
Collaborator

Choose a reason for hiding this comment

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

add logging

@vikrantpuppala vikrantpuppala force-pushed the fix/1247-date-epoch-day-in-complex-types branch from f43f071 to def7071 Compare March 9, 2026 13:47
vikrantpuppala and others added 3 commits March 9, 2026 13:47
… of date strings

When Arrow serializes DATE fields inside nested types (ARRAY, STRUCT, MAP),
getObject() returns epoch day integers rather than ISO-8601 date strings.
ComplexDataTypeParser.convertPrimitive() now falls back to parsing epoch day
integers via LocalDate.ofEpochDay() when Date.valueOf() fails.

Closes databricks#1247

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
… add changelog

- Wrap epoch-day fallback in try-catch so non-numeric invalid date strings
  (e.g., "2026/02/03") rethrow the original IllegalArgumentException instead
  of a NumberFormatException.
- Add test for invalid date string error behavior.
- Add NEXT_CHANGELOG.md entry for the user-facing bug fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
…E parsing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Vikrant Puppala <vikrant.puppala@databricks.com>
@vikrantpuppala vikrantpuppala force-pushed the fix/1247-date-epoch-day-in-complex-types branch from def7071 to 529df0f Compare March 9, 2026 13:47
@vikrantpuppala vikrantpuppala enabled auto-merge (squash) March 9, 2026 13:48
@vikrantpuppala vikrantpuppala merged commit c7291f5 into databricks:main Mar 9, 2026
15 checks passed
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] Date fields within ARRAY<STRUCT> types are serialized as Epoch Days (integers) rather than ISO-8601 strings.

6 participants