Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Temporal transforms put pre-epoch timestamps at `.999999` into the previous unit

Open Beginner friendly
#18,371 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@gitedmond is already working on this.

Since Oct 5, 2026.

  • #18375 by @gitedmond — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
java
Domain
databases

Research direction

Start at DateTimeUtil.convertMicros and DateTimeUtil.convertNanos, then trace how the year, month, day, and hour transforms use them. Add regression coverage for the exact pre-epoch boundary values described in the issue and verify the transforms remain monotonic and inclusive projection no longer prunes the matching row.

Written by the indexing model from the issue text.

Description

Apache Iceberg version

main (development)

Query engine

Other

Please describe the bug 🐞

DateTimeUtil.convertMicros and DateTimeUtil.convertNanos return the previous unit for a pre-epoch timestamp in the first second of a unit when its fraction is .999999 (.999999999 for nanos). This affects the year, month, day and hour transforms.

var day = Transforms.day().bind(Types.TimestampType.withoutZone());
long midnight = -86_400_000_000L; // 1969-12-31T00:00:00
day.apply(midnight + 999_998);    // -1
day.apply(midnight + 999_999);    // -2, expected -1
day.apply(midnight + 1_000_000);  // -1

The spec defines day as days from 1970-01-01, so 1969-12-31T00:00:00.999999 should be -1. The transform also stops being monotonic, which inclusive projection relies on, so Java's own scan skips a matching row:

// row 1969-12-31T00:00:00.999999 is written to partition ts_day = -2
Projections.inclusive(spec).project(greaterThanOrEqual("ts", midnight + 500_000));
// -> ts_day >= -1, so the file holding the row is pruned

Likelihood: low. It needs a pre-epoch timestamp, in the first second of an hour/day/month/year, with a fraction of exactly .999999 (.999999999 for nanos). Second- or millisecond-precision data never hits it. For random microsecond-precision pre-epoch values it's roughly 1 in 10^11 rows for day and 1 in 4×10^9 for hour.

Cause: the negative branch adds 1 to the fraction but not to the seconds:

long epochSecond = Math.floorDiv(micros, MICROS_PER_SECOND);
long nanoAdjustment = Math.floorMod(micros + 1, MICROS_PER_SECOND) * 1000;

At .999999, micros + 1 crosses into the next second but epochSecond does not, so the timestamp lands almost a second earlier. In the first second of a unit, that crosses into the previous unit.

Fix: Math.floorDiv(micros + 1, MICROS_PER_SECOND), and the same in convertNanos with NANOS_PER_SECOND. I checked the micros version against floor semantics for year, month, day and hour across ~47k values, including every unit boundary from 1900 to 1971: the current code is wrong for 3,446 of them, the fix for none.

iceberg-rust returns the calendar day for these values, see the iceberg-rust day transform fix.

Related: #18115 (same class of bug, rounding toward zero instead of down for pre-epoch values, but in microsecond conversion rather than the transforms), #9714 (transform rounding for negative values isn't specified). The +1/-1 adjustment comes from #1981.

Willingness to contribute
  • I can contribute a fix for this bug independently
  • I would be willing to contribute a fix for this bug with guidance from the Iceberg community
  • I cannot contribute a fix for this bug at this time
Dominant language
Java
Stars
9.3k
Forks
3.6k
Avg merge
3d 4h
Merged PRs (30d)
154

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from apache/iceberg

All issues in apache/iceberg

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.