Was this page helpful?
ScyllaDB Java Driver is available under the Apache v2 License. ScyllaDB Java Driver is a fork of DataStax Java Driver. See Copyright here.
This page provides more details about the various CQL time types, and the Java types they are mapped to in the driver.
CQL | Java | |
---|---|---|
date |
java.time.LocalDate |
|
time |
java.time.LocalTime |
|
timestamp |
java.time.Instant |
No time zone. Use Instant.atZone or register [TypeCodecs.ZONED_TIMESTAMP_SYSTEM], [TypeCodecs.ZONED_TIMESTAMP_UTC] or [TypeCodecs.zonedTimestampAt()] |
duration |
[CqlDuration] | Custom driver type; can't be accurately represented by any of the java.time types. |
CQL types date
and time
map directly to java.time.LocalDate
and java.time.LocalTime
.
These are simple, time-zone-free representations of date-only (yyyy-mm-dd
) and time-only
(HH:MM:SS[.fff]
) types.
CQL type timestamp
is the date-and-time representation, stored as a number of milliseconds since
the epoch (01/01/1970 UTC).
timestamp
does not store a time zone. This is not always obvious because clients generally do
use one for display. For instance, the following CQLSH snippet is from a machine in Pacific time:
cqlsh> CREATE TABLE test(t timestamp PRIMARY KEY);
cqlsh> INSERT INTO test (t) VALUES (dateof(now()));
cqlsh> SELECT * FROM test;
t
---------------------------------
2018-11-07 08:50:52.433000-0800
It looks like the timestamp has a zone (-0800
), but it is actually the client’s. If you force
CQLSH to a different zone and observe the same data, it will be displayed differently:
$ TZ=UTC cqlsh
cqlsh> SELECT * FROM test;
t
---------------------------------
2018-11-07 16:50:52.433000+0000
Internally, Cassandra only stores the raw number of milliseconds. You can observe that with a cast:
cqlsh> SELECT cast(t as bigint) FROM test;
cast(t as bigint)
-------------------
1541609452433
By default, the driver maps timestamp
to java.time.Instant
. This Java type is the closest to the
internal representation; in particular, it does not have a time zone. On the downside, this means
you can’t directly extract calendar fields (year, month, etc.). You need to call atZone
to perform
the conversion:
Row row = session.execute("SELECT t FROM test").one();
Instant instant = row.getInstant("t");
ZonedDateTime dateTime = instant.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println(dateTime.getYear());
Conversely, you can convert a ZonedDateTime
back to an Instant
with toInstant
.
If you want to automate those atZone
/toInstant
conversions, the driver comes with an optional
ZonedDateTime
codec, that must be registered explicitly with the session:
CqlSession session = CqlSession.builder()
.addTypeCodecs(TypeCodecs.ZONED_TIMESTAMP_UTC)
.build();
Row row = session.execute("SELECT t FROM test").one();
ZonedDateTime dateTime = row.get("t", GenericType.ZONED_DATE_TIME);
There are various constants and methods to obtain a codec instance for a particular zone:
TypeCodecs.ZONED_TIMESTAMP_SYSTEM: system default;
TypeCodecs.zonedTimestampAt(): user-provided.
Which zone you choose is application-dependent. The driver doesn’t map to ZonedDateTime
by default
because it would have to make an arbitrary choice; we want you to think about time zones explicitly
before you decide to use that type.
As already stated, timestamp
is stored as a number of milliseconds. If you try to write an
Instant
or ZonedDateTime
with higher precision through the driver, the sub-millisecond part will
be truncated:
CqlSession session =
CqlSession.builder()
.addTypeCodecs(TypeCodecs.ZONED_TIMESTAMP_UTC)
.build();
ZonedDateTime valueOnClient = ZonedDateTime.parse("2018-11-07T16:50:52.433395762Z");
// sub-millisecond digits ^^^^^^
session.execute(
SimpleStatement.newInstance("INSERT INTO test (t) VALUES (?)", valueOnClient));
ZonedDateTime valueInDb =
session.execute("SELECT * FROM test").one().get(0, GenericType.ZONED_DATE_TIME);
System.out.println(valueInDb);
// Prints "2018-11-07T16:50:52.433Z"
CQL type duration
represents a period in months, days and nanoseconds. The driver maps it to a
custom type: CqlDuration.
We deliberately avoided java.time.Period
, because it does not contain a nanoseconds part as
CqlDuration
does; and we also avoided java.time.Duration
, because it represents an absolute
time-based amount, regardless of the calendar, whereas CqlDuration
manipulates conceptual days and
months instead. Thus a CqlDuration
of “2 months” represents a different amount of time depending
on the date to which it is applied (because months have a different number of days, and because
daylight savings rules might also apply, etc).
CqlDuration
implements java.time.temporal.TemporalAmount
, so it interoperates nicely with the
JDK’s built-in temporal types:
ZonedDateTime dateTime = ZonedDateTime.parse("2018-10-04T00:00-07:00[America/Los_Angeles]");
System.out.println(dateTime.minus(CqlDuration.from("1h15s15ns")));
// prints "2018-10-03T22:59:44.999999985-07:00[America/Los_Angeles]"
Was this page helpful?
ScyllaDB Java Driver is available under the Apache v2 License. ScyllaDB Java Driver is a fork of DataStax Java Driver. See Copyright here.