Using `filter` for maps

Hi, I have a function that takes a timestamp as an argument and computes some data which is basically a map.
The map looks something like this:

({:description nil, :updated-at #object[ 0x64a8ec27 "2021-07-19T09:24:34.268000000Z"], :completed-by nil, :parent nil, :checklists nil, :last-message-author "unibot", :last-message nil, :process-whitelist-groups nil, :privacy "none", id:10, :whitelisted-groups nil, :type "group", :org-id 1, :outcome nil, :process-owners nil, :title "hjgf", :created-at #object[ 0x6038f825 "2021-07-19T09:24:34.268000000Z"], :origin-seq-no nil}  
{:description nil, :updated-at #object[ 0x53fbd4ee "2021-07-19T09:25:00.896000000Z"], :completed-by nil, :parent nil, :checklists nil, :last-message-author "unibot", :last-message nil, :org-id 1, :outcome nil, :process-owners nil, :title "hnbnb", :status-title "pending", :process-whitelist nil, :process-title nil, :canceled nil, :current-version nil, :priority nil, :status -1, :active nil, :id 20, :due-date nil, :count 0, :privacy-settings nil, :files [], :completed-at nil, :reminders nil, :version-comment nil, :groups nil, :version nil, :seq-no nil, :whitelist nil, :created-at #object[ 0x1988f98e "2021-07-19T09:25:00.896000000Z"], :breadcrumbs nil})

We can call this map as data. Now how to filter this data by providing a timestamp to fetch the :id and :title only if the time specified is >=?

I tried {:ID :Title (filter #(>= "2021-07-19" (:created-at %)) data)} but it didn’t work as expected…

{:ID :Title (filter #(>= "2021-07-19" (:created-at %)) data)}

This doesn’t make much sense to me, you create a map with key :ID and value :Title and then another key which will be the result of filter and then it has no value, so this should throw a compile error I assume?

Anyway, your problem appart from that, is that "2021-07-19" is a string, but your map contains Google cloud Timestamps. A string is never going to be equal to a Google cloud Timestamps. You need to convert your string to a Google cloud Timestamp first, and then you need to use the time comparison functions of Google cloud Timestamps, as it might not naturally work with >=.

How to convert the string to google cloud timestamps?

What’s the format of java.time.Instant?

I wrote another function to convert it.

(defn instant->cloud-timestamp
  "Convert `java.time.Instant` to ``"
  (when-not (nil? instance)
    ( (Timestamp/from instance))))
(->> (filter #(=> (instant->cloud-timestamp “2021-07-19T09:25:00.896000000Z” (:created-at %)) data)
         (mapv (comp :id)))

But getting an error No matching method from found taking 1 args @didibus

No need to at-mention people like that, people who responded previously will get a notification of your response, and people will answer in their own time.

Note that there are also chat communities for Clojure. If you are still struggling with basic concepts then it’s often easier to get help that way.

You need to learn about looking up methods on Java classes, since in this case you are dealing with interop with a Java library.

I’m also not sure what instance is going to be here? I would say instead of a String use an Instant, and then convert the Instant to a Google cloud Timestamp for the filtering:

(defn inst->goog-timestamp
  (Timestamp/of (Date/from inst)))

Where Timestamp is an import from Google cloud and Date is an import from java.util.

Now in your filter try:

(->> (filter #(=> (inst->goog-timestamp #inst "2021-07-19T09:25:00.896000000Z" (:created-at %)) data)
         (mapv (comp :id)))

Also not sure what => is, that looks like a custom macro. Oh…, you want >= I believe instead. The comp is also redundant, you can just pass :id on its own as the mapping function. And in general it would just be clearer if you did:

(->> data
     (filter #(>= (inst->goog-timestamp #inst "2021-07-19T09:25:00.896000000Z") (:created-at %)))
     (mapv :id))
1 Like