Repository navigation
Description
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
review(#10198, #10199, #10200): resolve date field overrides together…
fix(#10198, #10199, #10200, #10203): Cypher temporal semantics aligne…
lvca commentedon Oct 17, 2026
Fixed in #10222 (release 26.11.1). All the cases in the table now match Neo4j:
millisecond,microsecondandnanosecondgiven with a base value (time:,datetime:, ...) replace the whole fraction of the second.*.truncate()keeps its existing behavior.datetime({epochSeconds | epochMillis, timezone})reads the instant in that time zone.date({date, dayOfWeek})moves the date within its week.dayOfQuarterworks the same way within the quarter.datetime()accepts years outside 0000-9999, such as-0001-...and+10000-....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.
tae898 commentedon Oct 17, 2026
Verified on the merge commit
b28fa820fcagainst maina759246daa(where it was filed), with the statements from the issue, each run withdb.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.a759246daab28fa820fcRETURN toString(localtime({time: localtime('12:30:45.123456789'), nanosecond:5})) AS vRETURN toString(localtime({time: localtime('12:30:45.123456789'), millisecond:5})) AS vRETURN toString(localtime({time: localtime('12:30:45.123456789'), microsecond:5})) AS vRETURN toString(time({time: time('12:30:45.123456789+01:00'), nanosecond:5})) AS vRETURN toString(datetime({epochSeconds:1700000000, timezone:'Europe/Paris'})) AS vRETURN toString(datetime({epochSeconds:0, timezone:'+05:30'})) AS vRETURN toString(datetime({epochMillis:1700000000123, timezone:'Asia/Kolkata'})) AS vRETURN toString(datetime.fromepoch(0, 0)) AS vRETURN toString(date({date: date('2024-02-29'), dayOfWeek:1})) AS vRETURN toString(date({date: date('2024-02-29'), week:1})) AS vRETURN toString(datetime('-0001-12-31T23:59:59Z')) AS vRETURN toString(datetime('+10000-01-01T00:00Z')) AS vRETURN toString(localdatetime('-0001-12-31T23:59:59')) AS vRETURN toString(date('-0001-12-31')) AS vRETURN toString(datetime({year:-1, month:12, day:31, timezone:'Z'})) AS vRETURN toString(time({hour:12, timezone:'UTC'})) AS vRETURN toString(time({hour:12, timezone:'Asia/Tokyo'})) AS vRETURN toString(time.truncate('minute', time('12:30+05:45'), {timezone:'Asia/Tokyo'})) AS v18 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.fix(#10198, #10199, #10200, #10203): Cypher temporal semantics aligne…