Visitar URL original
Cypher temporal constructors ignore nanosecond/millisecond/microsecond overrides, the timezone of an epoch datetime and dayOfWeek; time() rejects zone names · Issue #10199 · ArcadeData/arcadedb · GitHub
Skip to content

Cypher temporal constructors ignore nanosecond/millisecond/microsecond overrides, the timezone of an epoch datetime and dayOfWeek; time() rejects zone names #10199

Closed

Description

@tae898

Cypher temporal constructors ignore or reject parts of their input: a nanosecond, millisecond or microsecond given with time: replaces only some digits of the fraction instead of the whole field; datetime({epochSeconds: ..., timezone: ...}) ignores the timezone; date({date: ..., dayOfWeek: 1}) ignores dayOfWeek; datetime() rejects years outside 0000 to 9999 that localdatetime() and date() accept; and time() with a zone name ('UTC', 'Asia/Tokyo') throws DateTimeException.

Identical on main (a759246daa) and 26.10.2 (e5040d0339), JDK 25 (-XX:+UseCompactObjectHeaders) and JDK 21, each statement run with db.command("opencypher", ...); Neo4j 2026.08.1 as the reference. Found by a temporal differential against Neo4j (8,668 generated queries; rows marked control agree). ArcadeDB's toString() also drops zero seconds (12:30 against Neo4j's 12:30:00); where that is the only difference in a row, it is formatting, not the point of this issue.

statement ArcadeDB Neo4j
RETURN toString(localtime({time: localtime('12:30:45.123456789'), nanosecond:5})) AS v 12:30:45.123456005 12:30:45.000000005
RETURN toString(localtime({time: localtime('12:30:45.123456789'), millisecond:5})) AS v 12:30:45.005456789 12:30:45.005
RETURN toString(localtime({time: localtime('12:30:45.123456789'), microsecond:5})) AS v 12:30:45.123005789 12:30:45.000005
RETURN toString(time({time: time('12:30:45.123456789+01:00'), nanosecond:5})) AS v 12:30:45.123456005+01:00 12:30:45.000000005+01:00
RETURN toString(datetime({epochSeconds:1700000000, timezone:'Europe/Paris'})) AS v 2023-11-14T22:13:20Z 2023-11-14T23:13:20+01:00[Europe/Paris]
RETURN toString(datetime({epochSeconds:0, timezone:'+05:30'})) AS v 1970-01-01T00:00Z 1970-01-01T05:30:00+05:30
RETURN toString(datetime({epochMillis:1700000000123, timezone:'Asia/Kolkata'})) AS v 2023-11-14T22:13:20.123Z 2023-11-15T03:43:20.123+05:30[Asia/Kolkata]
RETURN toString(datetime.fromepoch(0, 0)) AS v 1970-01-01T00:00Z 1970-01-01T00:00:00Z
RETURN toString(date({date: date('2024-02-29'), dayOfWeek:1})) AS v 2024-02-29 2024-02-26
RETURN toString(date({date: date('2024-02-29'), week:1})) AS v 2024-01-04 2024-01-04
RETURN toString(datetime('-0001-12-31T23:59:59Z')) AS v error: CommandSemanticException: datetime() cannot parse '-0001-12-31T23:59:59Z' as a datetime or timezone -0001-12-31T23:59:59Z
RETURN toString(datetime('+10000-01-01T00:00Z')) AS v error: CommandSemanticException: datetime() cannot parse '+10000-01-01T00:00Z' as a datetime or timezone +10000-01-01T00:00:00Z
RETURN toString(localdatetime('-0001-12-31T23:59:59')) AS v -0001-12-31T23:59:59 -0001-12-31T23:59:59
RETURN toString(date('-0001-12-31')) AS v -0001-12-31 -0001-12-31
RETURN toString(datetime({year:-1, month:12, day:31, timezone:'Z'})) AS v -0001-12-31T00:00Z -0001-12-31T00:00:00Z
RETURN toString(time({hour:12, timezone:'UTC'})) AS v error: DateTimeException: Invalid ID for ZoneOffset, non numeric characters found: UTC 12:00:00Z
RETURN toString(time({hour:12, timezone:'Asia/Tokyo'})) AS v error: DateTimeException: Invalid ID for ZoneOffset, invalid format: Asia/Tokyo 12:00:00+09:00
RETURN toString(time.truncate('minute', time('12:30+05:45'), {timezone:'Asia/Tokyo'})) AS v error: DateTimeException: Invalid ID for ZoneOffset, invalid format: Asia/Tokyo 12:30:00+09:00

The program that ran the ArcadeDB side is a loop of db.command("opencypher", statement) over the statements above, one fresh database, each statement in a transaction that is rolled back.

Activity

  1. added this to the 26.11.1 milestone on Oct 17, 2026
  2. added
    in progressThe team is actively working on this issue
    on Oct 17, 2026
  3. self-assigned this
    on Oct 17, 2026
  4. added 2 commits that reference this issue on Oct 17, 2026
  5. lvca commented on Oct 17, 2026

    @lvca
    Member

    Fixed in #10222 (release 26.11.1). All the cases in the table now match Neo4j:

    • Sub-second overrides: millisecond, microsecond and nanosecond given with a base value (time:, datetime:, ...) replace the whole fraction of the second. *.truncate() keeps its existing behavior.
    • Epoch with timezone: datetime({epochSeconds | epochMillis, timezone}) reads the instant in that time zone.
    • dayOfWeek: date({date, dayOfWeek}) moves the date within its week. dayOfQuarter works the same way within the quarter.
    • Year range: datetime() accepts years outside 0000-9999, such as -0001-... and +10000-....
    • Named zones: time() accepts a zone name such as 'UTC' or 'Asia/Tokyo' and uses that zone's current offset.

    ❤️ Thanks for helping make ArcadeDB better! ArcadeDB is free and open source, sustained by its community. If it's useful to you or your company, please consider becoming a sponsor to keep development going.

  6. removed
    in progressThe team is actively working on this issue
    on Oct 17, 2026
  7. tae898 commented on Oct 17, 2026

    @tae898
    ContributorAuthor

    Verified on the merge commit b28fa820fc against main a759246daa (where it was filed), with the statements from the issue, each run with db.command("opencypher", ...) in a fresh database, on eclipse-temurin 25 (-XX:+UseCompactObjectHeaders) and 21 (identical on both JDKs, before and after); Neo4j 2026.08.1 as the reference.

    statement a759246daa b28fa820fc Neo4j
    RETURN toString(localtime({time: localtime('12:30:45.123456789'), nanosecond:5})) AS v 12:30:45.123456005 12:30:45.000000005 12:30:45.000000005
    RETURN toString(localtime({time: localtime('12:30:45.123456789'), millisecond:5})) AS v 12:30:45.005456789 12:30:45.005 12:30:45.005
    RETURN toString(localtime({time: localtime('12:30:45.123456789'), microsecond:5})) AS v 12:30:45.123005789 12:30:45.000005 12:30:45.000005
    RETURN toString(time({time: time('12:30:45.123456789+01:00'), nanosecond:5})) AS v 12:30:45.123456005+01:00 12:30:45.000000005+01:00 12:30:45.000000005+01:00
    RETURN toString(datetime({epochSeconds:1700000000, timezone:'Europe/Paris'})) AS v 2023-11-14T22:13:20Z 2023-11-14T23:13:20+01:00[Europe/Paris] 2023-11-14T23:13:20+01:00[Europe/Paris]
    RETURN toString(datetime({epochSeconds:0, timezone:'+05:30'})) AS v 1970-01-01T00:00Z 1970-01-01T05:30+05:30 1970-01-01T05:30:00+05:30
    RETURN toString(datetime({epochMillis:1700000000123, timezone:'Asia/Kolkata'})) AS v 2023-11-14T22:13:20.123Z 2023-11-15T03:43:20.123+05:30[Asia/Kolkata] 2023-11-15T03:43:20.123+05:30[Asia/Kolkata]
    RETURN toString(datetime.fromepoch(0, 0)) AS v 1970-01-01T00:00Z 1970-01-01T00:00Z 1970-01-01T00:00:00Z
    RETURN toString(date({date: date('2024-02-29'), dayOfWeek:1})) AS v 2024-02-29 2024-02-26 2024-02-26
    RETURN toString(date({date: date('2024-02-29'), week:1})) AS v 2024-01-04 2024-01-04 2024-01-04
    RETURN toString(datetime('-0001-12-31T23:59:59Z')) AS v error: CommandSemanticException: datetime() cannot parse '-0001-12-31T23:59:59Z' as a date -0001-12-31T23:59:59Z -0001-12-31T23:59:59Z
    RETURN toString(datetime('+10000-01-01T00:00Z')) AS v error: CommandSemanticException: datetime() cannot parse '+10000-01-01T00:00Z' as a dateti +10000-01-01T00:00Z +10000-01-01T00:00:00Z
    RETURN toString(localdatetime('-0001-12-31T23:59:59')) AS v -0001-12-31T23:59:59 -0001-12-31T23:59:59 -0001-12-31T23:59:59
    RETURN toString(date('-0001-12-31')) AS v -0001-12-31 -0001-12-31 -0001-12-31
    RETURN toString(datetime({year:-1, month:12, day:31, timezone:'Z'})) AS v -0001-12-31T00:00Z -0001-12-31T00:00Z -0001-12-31T00:00:00Z
    RETURN toString(time({hour:12, timezone:'UTC'})) AS v error: DateTimeException: Invalid ID for ZoneOffset, non numeric characters found: UTC 12:00Z 12:00:00Z
    RETURN toString(time({hour:12, timezone:'Asia/Tokyo'})) AS v error: DateTimeException: Invalid ID for ZoneOffset, invalid format: Asia/Tokyo 12:00+09:00 12:00:00+09:00
    RETURN toString(time.truncate('minute', time('12:30+05:45'), {timezone:'Asia/Tokyo'})) AS v error: DateTimeException: Invalid ID for ZoneOffset, invalid format: Asia/Tokyo 12:30+09:00 12:30:00+09:00

    18 statements: 18 now answer as Neo4j does (7 of them differ only in toString() dropping zero seconds, which the issue set aside). Thanks for the quick fix.

  8. added a commit that references this issue on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugopencypherseverity:majorA feature is broken or returns wrong results, with no practical workaround

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions