Skip to content

Comparing a timestamp cast to a time zone against a literal returns wrong results #25941

Closed

Description

@neilconway

Describe the bug

A filter that casts a timestamp without a time zone to one with a time zone, then compares it to a timestamp literal, returns the wrong rows. Both sides of the comparison display the same value. The same comparison against a column instead of a literal gives the right answer.

To Reproduce

CREATE TABLE t AS VALUES (TIMESTAMP '2024-01-01 10:00:00');
CREATE TABLE l AS SELECT arrow_cast('2024-01-01T10:00:00+05:00', 'Timestamp(Nanosecond, Some("+05:00"))') AS v;

-- Both sides are 2024-01-01T10:00:00+05:00
SELECT arrow_cast(column1, 'Timestamp(Nanosecond, Some("+05:00"))') AS lhs, v AS rhs FROM t, l;

-- Compare against a column: 1 row (correct)
SELECT count(*) FROM t, l
WHERE arrow_cast(t.column1, 'Timestamp(Nanosecond, Some("+05:00"))') = l.v;

-- Compare against the same value as a literal: 0 rows (wrong)
SELECT count(*) FROM t
WHERE arrow_cast(column1, 'Timestamp(Nanosecond, Some("+05:00"))')
    = arrow_cast('2024-01-01T10:00:00+05:00', 'Timestamp(Nanosecond, Some("+05:00"))');

It also happens with the more common ::timestamptz form when a session time zone is set:

SET datafusion.execution.time_zone = '+05:00';
CREATE TABLE t AS VALUES (TIMESTAMP '2024-01-01 10:00:00');
SELECT column1::timestamptz FROM t;  -- 2024-01-01T10:00:00+05:00
SELECT count(*) FROM t WHERE column1::timestamptz = TIMESTAMPTZ '2024-01-01 10:00:00+05:00';  -- 0

Expected behavior

Both literal comparisons should return 1, matching the column comparison.

Additional context

Reproduced on main at commit 242b96c. With a +00:00 or UTC time zone the results are correct. With +05:00 or -03:00, the literal comparison returns 0 rows.

This bug report was generated by Claude.

Activity

  1. DHRUV6029 commented on Oct 5, 2026

    @DHRUV6029

    take

  2. DHRUV6029 commented on Oct 5, 2026

    @DHRUV6029

    Hi @Ruchirtripathi, thanks for working on #25099!

    While digging into this issue I realized it's the same bug as #25095, just triggered a bit differently. It uses a fixed-offset time zone like +05:00 or -03:00 instead of a named zone like Asia/Singapore. For example:

    CREATE TABLE t AS VALUES (TIMESTAMP '2024-01-01 10:00:00');
    
    SELECT count(*) FROM t
    WHERE arrow_cast(column1, 'Timestamp(Nanosecond, Some("+05:00"))')
        = arrow_cast('2024-01-01T10:00:00+05:00', 'Timestamp(Nanosecond, Some("+05:00"))');
    -- returns 0 on main, should be 1

    The root cause is the same: the unwrap_cast rewrite copies the literal's value without applying the timezone shift.

    I applied the change from #25099 on top of current main (6e319bddd) and ran all the queries from this issue. They return the right results now.

    Since #25099 fixes both issues, could you add Closes #25941 to its description? That way both get closed when it merges.

    Thanks!

  3. AdamGS commented on Nov 2, 2026

    @AdamGS
    Contributor

    On current main (9411463), this issue seems to be solved, the following SLT tests passes:

    statement ok
    CREATE TABLE t AS VALUES (TIMESTAMP '2024-01-01 10:00:00');
    
    statement ok
    CREATE TABLE l AS SELECT arrow_cast('2024-01-01T10:00:00+05:00', 'Timestamp(Nanosecond, Some("+05:00"))') AS v;
    
    # Both sides are 2024-01-01T10:00:00+05:00
    query PP
    SELECT arrow_cast(column1, 'Timestamp(Nanosecond, Some("+05:00"))') AS lhs, v AS rhs FROM t, l;
    ----
    2024-01-01T10:00:00+05:00 2024-01-01T10:00:00+05:00
    
    # Compare against a column: 1 row (correct)
    query I
    SELECT count(*) FROM t, l
    WHERE arrow_cast(t.column1, 'Timestamp(Nanosecond, Some("+05:00"))') = l.v;
    ----
    1
    
    query I
    SELECT count(*) FROM t
    WHERE arrow_cast(column1, 'Timestamp(Nanosecond, Some("+05:00"))')
        = arrow_cast('2024-01-01T10:00:00+05:00', 'Timestamp(Nanosecond, Some("+05:00"))');
    ----
    1
    
    
    statement ok
    SET datafusion.execution.time_zone = '+05:00';
    
    statement ok
    CREATE TABLE t2 AS VALUES (TIMESTAMP '2024-01-01 10:00:00');
    
    
    # 2024-01-01T10:00:00+05:00
    query P
    SELECT column1::timestamptz FROM t2;
    ----
    2024-01-01T10:00:00+05:00
    
    # 0
    query I
    SELECT count(*) FROM t2 WHERE column1::timestamptz = TIMESTAMPTZ '2024-01-01 10:00:00+05:00';
    ----
    1
    
    statement ok
    RESET datafusion.execution.time_zone;
    
    statement ok
    DROP TABLE t;
    
    statement ok
    DROP TABLE l;
    
    statement ok
    DROP TABLE t2;
    
  4. added a commit that references this issue on Nov 2, 2026
    17401bb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions