DuckDB version 1.4.3
Using the data type TimestampTZ (Timestamp with Time Zone) some timestamps can not be saved correctly. We give an example below for the Timestamp ISO: 2025-10-25T23:15:00Z
The underlaying JAVA-implementation uses OffsetDateTime to bind the millisecond-value with the db-column.
We give the code in KiScript, that uses the JDBC-driver, prepared statements and so on:
// create a table with one column ts of time TimestampTZ
DuckDB.createTable(c, "test1", Reader.emptyRow("Timestamp ts").desc())
// prepare an insert-statement
let w = c.prepare("insert into test1 (ts) values (?)")
// Write 1761434100000L, which is ms since 1970-01-01: ISO: 2025-10-25T23:15:00Z,
w.setTimestamp(0, 1761434100000L)
w.execute()
// Read the value back from database:
Reader r = c.select("* from test1")
r.next()
(r[0] as Timestamp).asStringISO()
// The result (Timestamp ISO-Format) will be 2025-10-25T22:15:00Z
// the millisecond value is: 1761430500000L
c.select("data_type from information_schema.columns where table_name = 'test1' and column_name = 'ts'")
=>
TIMESTAMP WITH TIME ZONE
Most timestamps are correct, some can not be stored and will be mapped to a different timestamp.
The expectation is that for all written timestamps the millisecond-value (UTC since 1970-01-01) the value does not change after read.
Interestingly, if we try to insert the Timestamp without bindings, the result is different, but also not correct:
// add the above timestamp as ISO-Timestamp
c.execute("insert into test1 (ts) values ('2025-10-25T23:15:00Z')")
// read it back
c.select("* from test1")
you will get:
1761437700000 which is 2025-10-26T00:15:00Z in ISO format
Unfortunately this lack is crucial for time series evaluations. Our work - around is not to use TimestampTZ columns but a bigint to store the milliseconds directly.