I have a database with keys storing times in UTC in ISO 8601 format, like so:
(data:key1)
{ "time": "2023-12-10T10:42:50.277Z" }
(data:key2)
{ "time": "2023-12-15T19:02:40.308Z" }
...
I want to aggregate data in these keys in some way, let's say I want to count the number of keys whose times are between 2023-12-10 and 2023-12-29.
Redis includes the FT.AGGREGATE
command in its RediSearch module, with an APPLY
subcommand which can be used to transform data using different types of expressions. To convert string-based times to/from numeric values, two transformations listed in the docs seem good:
timefmt(x, [fmt])
Return a formatted time string based on a numeric timestamp value x. See strftime for formatting options. Not specifying fmt is equivalent to %FT%TZ.parsetime(timesharing, [fmt])
The opposite of timefmt() - parse a time format using a given format string
However, I cannot find a way to make that work. I first create a search index with FT.CREATE mySearch ON JSON PREFIX 1 data: SCHEMA $.time AS time TEXT
, then to aggregate I call FT.AGGREGATE mySearch "*" APPLY "parsetime(@time, '%G-%m-%dT%H:%M:%S.%fZ')" as numericTime
, to which the response is:
1) "1"
2) 1) "time"
2) "2023-12-14T20:42:50.277Z"
3) "numericTime"
4) "null" // <- this should be a unix timestamp instead of null
What am I doing wrong, and what's the correct way to parse these time strings into numeric values?
I spent 20 minutes poking around to see how Redis responds to various strings containing dates and times. Here's what I've learned:
null
if you give it formatting options that are invalid. I tried it with %q
, which is very invalid, to confirm this.%f
for microseconds while the Python ones do. In fact, it doesn't support fractions of seconds at all. So, this isn't going to work.In my estimation, you have two choices:
A couple of other things of note:
%G
for the year. It should be %Y
. %G
is the week-based year, not the actual year. ISO 8601 dates use the actual year.%F
is short for %Y-%m-%d
and %T
is short for %H:%M:%S
.%Z
to match the timezone. It's a little more robust than just using a hard-coded Z
as you might encounter times that specify the timezone.All this said, I could revise your parsing string to be %FT%T%Z
but I think that %Y-%m-%dT%H:%M:%S%Z
is probably easier to read. Up to personal preference!
Anyhow, that was kind of a long answer but I certainly hope it helps!