Repository navigation
feat(lance): support TIMESTAMP_LTZ type - #479
Merged
Merged
Conversation
SteNicholas
force-pushed
the
PAIMON-476
branch
2 times, most recently
from
October 29, 2026 00:48
262505c to
b1881fb
Compare
lxy-9602
reviewed
Oct 29, 2026
Accept TIMESTAMP_LTZ, including inside ARRAY and ROW, in Lance schema validation, as Paimon Java does. Lance 0.39 cannot parse a time zone id containing ':', and Paimon Java always writes TIMESTAMP_LTZ to Lance as an Arrow timestamp with the UTC time zone. LanceFormatWriter now imports batches with a copy of the schema whose zoned timestamps are relabelled as UTC. Only the Arrow type changes, not the values, and the file stores what Java writes whatever the local time zone is. Lance returns those timestamps as UTC while the read schema carries the local time zone. Move AlignTimestampTimezones from the Vortex reader into NestedProjectionUtils and use it in both readers to relabel zoned leaves before AlignArrayToReadType. As a shared utility it now takes an arrow::Array and also follows MAP keys and values. Document how Lance stores TIMESTAMP WITH LOCAL TIME ZONE.
SteNicholas
force-pushed
the
PAIMON-476
branch
from
October 29, 2026 17:27
b1881fb to
51f436e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Linked issue: close #476
Paimon Java accepts
TIMESTAMP_LTZ(TIMESTAMP WITH LOCAL TIME ZONE) columns in Lance data filessince apache/paimon#10558. Paimon C++ rejected every Arrow timestamp with a time zone in
SchemaValidation::ValidateLanceDataField()withLance file format does not support type LOCAL_ZONED_TIMESTAMP, whether Lance was selected byfile.format,file-format-per-levelorchangelog-file-format.Removing that check alone is not enough, because the two sides put different time zones on the
Arrow type:
Timestamp(unit, "UTC")(ArrowFieldTypeConversion), and itsvalidator relies on that: Lance 0.39 stores the type as
timestamp:<unit>:<zone>and cannotparse a zone id containing
:such asGMT-10:00.DateTimeUtils::GetLocalTimezoneName(), a host-dependentzone id that may contain
:.This change:
ValidateLanceDataField(), including inside ARRAY and ROW, asJava's
LanceRowTypeVisitordoes.LanceFormatWriterimport each batch with a copy of the writer schema whose zonedtimestamps, top level and nested, carry the
UTCtime zone. The values are instants since theepoch, so only the Arrow type changes, and the file stores what Java writes whatever the local
time zone is.
UTCtimestamps Lance returns with the read schema's local zone inLanceFileBatchReader::AlignBatch(), beforeAlignArrayToReadType(), which would otherwisereject the zone difference. The helper,
AlignTimestampTimezones, moves from the Vortexreader's anonymous namespace into
NestedProjectionUtilsand is used by both readers. It takesand returns an
arrow::Array, matches ROW children by name, and follows ARRAY, fixed-size listand MAP keys and values. It only relabels a timestamp when both sides have a zone and the same
unit.
LanceStatsExtractor::CreateEmptyStats()already handlesTIMESTAMPwhatever its zone.Tests
SchemaValidationTest.TestLanceDataTypes: LTZ at precisions 0, 3, 6 and 9 withUTC,Asia/Shanghai,GMT-10:00and+08:00zones, in ARRAY and inROW<ARRAY<...>>, moves fromthe rejected to the accepted fields. An LTZ array is also accepted when Lance is selected
through
file-format-per-levelorchangelog-file-format.NestedProjectionUtilsTest.AlignTimestampTimezonesRelabelsZonedLeavesOfSameUnit: top-level,ROW, ARRAY, fixed-size list and MAP key and value leaves are relabelled; identical types, a unit
change and a timestamp without a zone on either side are left unchanged. It also covers sliced
input and checks that the input is not modified.
NestedProjectionUtilsTest.AlignTimestampTimezonesMatchesStructChildrenByName: a ROW child thatthe read type does not name keeps its zone, and the child it names is relabelled although it
sits at another position, as when the Vortex reader passes a batch it has not pruned.
LanceFileFormatTest.WriteThenReadSupportedTypes: adds LTZ columns at precisions 0, 3, 6 and 9,ARRAY<LTZ>andROW<LTZ>in theGMT-10:00zone, reads them back in that zone and checksthat the file schema stores
UTC.WriteAndReadInteTest.TestAppendTimestampTypeandTestPkTimestampTypenow also run forLance.
LanceTimestampLtzInteTest.TestWriteAndReadInPinnedTimezone: append and primary-key tablesunder
UTC,Asia/ShanghaiandPacific/Honolulu, with nested LTZ, an LTZ column added byschema evolution, a reordered projection, and one column changed from
TIMESTAMP(6)toTIMESTAMP_LTZ(6)and another the other way. Files written before the type change areconverted in the local time zone, as Java's
TimestampToTimestampCastRuledoes withTimeZone.getDefault();ScanAndReadInteTest.TestCastTimestampTypechecks the same conversionon Java-written Parquet and ORC files.
ScanAndReadInteTest.TestLanceLtzCompatibility: reads the newlance/append_ltz_java_compatfixture (Paimon Java at
535a5c9, JVM time zoneGMT-10:00) andlance/append_ltz_python_compatfixture (Paimon Python at63ffd40) underAsia/Shanghai, atboth snapshots and with a reordered projection. Both fixtures hold the same LTZ(0/3/6/9),
ARRAY<LTZ(6)>andROW<number INT, ts LTZ(3)>values, and both writers store every LTZ leafas
UTC. The existingappend_java_compatandappend_python_compatfixtures are unchanged.API and Format
No API changes in
include/. No storage format changes: LTZ is written to Lance as an Arrowtimestamp with the
UTCtime zone, as in Paimon Java.Documentation
Yes.
docs/source/user_guide/data_types.rstdescribes how Lance data files storeTIMESTAMP WITH LOCAL TIME ZONE: as an Arrow timestamp with theUTCtime zone whatever thelocal time zone is, returned in the local time zone on read.
Generative AI tooling
Generated-by: Claude Code 2.1.311 (Claude Opus 5.5)
🤖 Generated with Claude Code