2

I have a timestamp column in a Cassandra table, how do i get the day of week from the timestamp column using cql?

Shankar
  • 8,529
  • 26
  • 90
  • 159

2 Answers2

3

There isn't support out of the box for this but

If using the CQL is a must you can have a look at the User Defined Functions:

http://cassandra.apache.org/doc/latest/cql/functions.html

http://www.datastax.com/dev/blog/user-defined-functions-in-cassandra-3-0

http://docs.datastax.com/en//cql/latest/cql/cql_using/useCreateUDF.html

Then you could use something as simple as:

How to determine day of week by passing specific date?

or even something like

Aggregation with Group By date in Spark SQL

And then you have a UDF that gives you day of the week when you are working with a dates.

Community
  • 1
  • 1
Marko Švaljek
  • 2,071
  • 1
  • 14
  • 26
0

Maybe this answer will be helpful for some one still looking for an answer in 2022. You can create an user defined function:

CREATE OR REPLACE FUNCTION DOW(
  input_date_string varchar,
  date_pattern varchar
) 
  CALLED ON NULL INPUT 
  RETURNS int 
  LANGUAGE java AS 
  '
    int ret = -1;
    try {
      ret = java.time.LocalDate.parse(input_date_string, java.time.format.DateTimeFormatter.ofPattern(date_pattern))
            .getDayOfWeek()
            .getValue();
    } catch (java.lang.Exception ex) {
      // error, do nothing here and -1 will be returned
    }
    return ret;
 ';

Test

cqlsh:store> create table testdate(key int PRIMARY KEY , date_string varchar );
... insert some date_strings ...
INSERT INTO testdate (key , date_string ) VALUES ( 9, '2022-11-22');
...

cqlsh:store> select date_string, dow(date_string, 'yyyy-MM-dd') from testdate;
 date_string | store.dow(date_string, 'yyyy-MM-dd')
-------------+--------------------------------------
  50/11/2022 |                                   -1
  2022-11-23 |                                    3
  19/11/2024 |                                   -1
  2022-11-21 |                                    1
  19/11/2023 |                                   -1
 19/11/20249 |                                   -1
  2022-11-20 |                                    7
  50/aa/2022 |                                   -1
  2022-11-22 |                                    2
  19/11/2024 |                                   -1

Similar function with timestamp argument

CREATE OR REPLACE FUNCTION DOW_TS(
  input_date_time timestamp,
  zone_id varchar
) 
  CALLED ON NULL INPUT 
  RETURNS int 
  LANGUAGE java AS 
  '
    int ret = -1;
    try {
      ret = input_date_time.toInstant().atZone(java.time.ZoneId.of(zone_id)).toOffsetDateTime()
        .getDayOfWeek()
        .getValue();
    } catch (java.lang.Exception ex) {
      // error, do nothing here and -1 will be returned
    }
    return ret;
  ';

Test

cqlsh:store> select id, dt, dow_ts(dt, 'UTC'), dow_ts(dt,'WHAT') from testdt;

 id | dt                              | store.dow_ts(dt, 'UTC') | store.dow_ts(dt, 'WHAT')
----+---------------------------------+-------------------------+--------------------------
  1 | 2022-11-19 14:30:47.420000+0000 |                       6 |                       -1

Above functions had been tested with below cassandra's setup:

INFO  [main] 2022-11-19 12:25:47,004 CassandraDaemon.java:632 - JVM vendor/version: OpenJDK 64-Bit Server VM/11.0.17
INFO  [main] 2022-11-19 12:25:50,737 StorageService.java:736 - Cassandra version: 4.0.7
INFO  [main] 2022-11-19 12:25:50,738 StorageService.java:737 - CQL version: 3.4.5

References:

Hint: you should ensure to set "enable_user_defined_functions: true" in /etc/cassandra/cassandra.yaml. With docker option above (https://cassandra.apache.org/_/quickstart.html), you do a quick hack as below

$ docker run --rm -d --name cassandra --hostname cassandra --network cassandra cassandra

$ docker cp cassandra:/etc/cassandra/cassandra.yaml .

Use your favorite editor to change "enable_user_defined_functions: false" to "enable_user_defined_functions: true" in "$(pwd)"/cassandra.yaml

$ docker run --rm -d --name cassandra --hostname cassandra --network cassandra --mount type=bind,source="$(pwd)"/cassandra.yaml,target=/etc/cassandra/cassandra.yaml cassandra

If you have very old cassandra version, which does not support java8 then maybe below altenative would work (see https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week)

CREATE OR REPLACE FUNCTION DOW_Tomohiko_Sakamoto(
  input_date_time timestamp
) 
  CALLED ON NULL INPUT 
  RETURNS int 
  LANGUAGE java AS 
'
    int y = input_date_time.getYear() + 1900;
    int m = input_date_time.getMonth() + 1;
    int d = input_date_time.getDate();

    int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
    if (m < 3) {
        y -= 1;
    }
    int ret = (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
    if (ret == 0) {
        ret = 7;
    }
    return ret;
';

TEST

cqlsh:store> insert into data(id, dt ) VALUES (2, '2022-11-19 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (3, '2022-11-21 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (4, '2022-11-23 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (5, '2022-11-24 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (7, '2022-11-25 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (8, '2022-11-26 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (9, '2022-11-27 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (10, '2022-11-28 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (11, '2020-02-29 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (12, '2020-02-30 00:00:00+0000');
cqlsh:store> insert into data(id, dt ) VALUES (13, '2020-02-31 00:00:00+0000');

cqlsh:store> select id, dt, dow_ts(dt,'UTC'), DOW_Tomohiko_Sakamoto(dt) from data;

 id | dt                              | store.dow_ts(dt, 'UTC') | store.dow_tomohiko_sakamoto(dt)
----+---------------------------------+-------------------------+---------------------------------
  5 | 2022-11-24 00:00:00.000000+0000 |                       4 |                               4
 10 | 2022-11-28 00:00:00.000000+0000 |                       1 |                               1
 13 | 2020-02-29 00:00:00.000000+0000 |                       6 |                               6
 11 | 2020-02-29 00:00:00.000000+0000 |                       6 |                               6
  1 | 2022-11-20 17:43:28.568000+0000 |                       7 |                               7
  8 | 2022-11-26 00:00:00.000000+0000 |                       6 |                               6
  2 | 2022-11-19 00:00:00.000000+0000 |                       6 |                               6
  4 | 2022-11-23 00:00:00.000000+0000 |                       3 |                               3
  7 | 2022-11-25 00:00:00.000000+0000 |                       5 |                               5
  9 | 2022-11-27 00:00:00.000000+0000 |                       7 |                               7
 12 | 2020-02-29 00:00:00.000000+0000 |                       6 |                               6
  3 | 2022-11-21 00:00:00.000000+0000 |                       1 |                               1
dreadlock
  • 106
  • 3