You're viewing documentation for a previous version of Scylla Java Driver. Switch to the latest stable version.
This page provides more details about the various CQL time types, and the Java types they are mapped to in the driver.
| CQL | Java | |
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. |
time map directly to
These are simple, time-zone-free representations of date-only (
yyyy-mm-dd) and time-only
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
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
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
If you want to automate those
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;
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
ZonedDateTime with higher precision through the driver, the sub-millisecond part will
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"
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).
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]"