Skip to content

Datetime filter rounding bug on [UTC] property #877

@havardthom

Description

@havardthom

Bug Report

Current behaviour

Using neo4j.time.DateTime().to_native() as query param stores datetime property as 2022-12-13T00:00:00[UTC]
Using datetime.datetime() as query param stores datetime property as 2022-12-13T00:00:00Z

Matching nodes MATCH (t:Test) WHERE t.datetime <= datetime($dtFilter) seems to behave differently for [UTC] datetime property vs Z datetime property. Seems like a rounding bug.

Expected behaviour

neo4j.time.DateTime().to_native() and datetime.datetime() query parameter should store datetime property in same format.
See #610

MATCH (t:Test) WHERE t.datetime <= datetime($dtFilter) should behave the same for [UTC] datetime property and Z datetime property.

Reproduced code:

import asyncio
from datetime import datetime, timezone

import neo4j


async def create_test_nodes_tx(tx):
    datetimes = [
        datetime.fromisoformat("2022-12-13T00:00:00.000000+00:00"),
        datetime.fromisoformat("2022-12-13T01:00:00.000000+00:00"),
        datetime.fromisoformat("2022-12-13T02:00:00.000000+00:00"),
        datetime.fromisoformat("2022-12-13T03:00:00.000000+00:00")
    ]

    for dt in datetimes:
        result = await tx.run("RETURN datetime($dt) AS datetime", dt=dt)
        record = await result.single(strict=True)

        dt_neo4j_native = record["datetime"].to_native()
        await tx.run("CREATE (t:Test) SET t.datetime = $dt", dt=dt_neo4j_native)
        # Property saved as datetime: "2022-12-13T00:00:00[UTC]"

        await tx.run("CREATE (t:Test) SET t.datetime = $dt", dt=dt)
        # Property saved as datetime: "2022-12-13T00:00:00Z"


async def get_test_nodes_filtered_tx(tx):
    dt_filters = [
        datetime.fromisoformat("2022-12-13T03:00:00.000000+00:00"), # <Record count=7>
        neo4j.time.DateTime(2022, 12, 13, 3, 0, 0, 0, tzinfo=timezone.utc).to_native(), # <Record count=7>
        datetime.fromisoformat("2022-12-13T03:00:00.000001+00:00"), # <Record count=8>
        neo4j.time.DateTime(2022, 12, 13, 3, 0, 0, 1000, tzinfo=timezone.utc).to_native(), # <Record count=8>
    ]
    query = """
        MATCH (t:Test)
        WHERE t.datetime <= datetime($dtFilter)
        RETURN count(*) AS count
    """
    for dt_filter in dt_filters:
        result = await tx.run(query, dtFilter=dt_filter)
        record = await result.single(strict=True)
        print(record)
        # Expecting count=8, "2022-12-13T03:00:00[UTC]" is not matched in some cases


async def main():
    uri = "neo4j://localhost:7687"
    driver = neo4j.AsyncGraphDatabase.driver(uri, auth=("neo4j", "pass"),)

    async with driver.session() as session:
        await session.execute_write(create_test_nodes_tx)
        await session.execute_read(get_test_nodes_filtered_tx)


asyncio.run(main())

My Environment

Python Version: 3.10.8
Driver Version: 5.1.0
Server Version and Edition: 4.4.6 Community

Possibly related:
#306
#748

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions