Fork me on GitHub
#clojure
<
2023-07-15
>
Kent Bull00:07:23

How do I get next.jdbc to recognize a UUID type for an ID for get-by-id? It works for find-by-keys

(defn find-holder-by-id! [db holder-id]
  (sql/find-by-keys db :wallet_holders {:guid holder-id}))
Yet not for get-by-id
(defn find-holder-by-id! [db holder-id]
  (sql/get-by-id db :wallet_holders :guid holder-id))
The name of my primary key field is “guid” in the database. PostgreSQL.

seancorfield01:07:38

Per the docs https://cljdoc.org/d/com.github.seancorfield/next.jdbc/1.3.883/api/next.jdbc.sql#get-by-id if you need to specify the pk-name you must also provide opts (which can be {})

seancorfield01:07:22

So it would be (sql/get-by-id db :wallet_holders holder-id :guid {})

❤️ 2
Kent Bull01:07:31

Ah, thank you. Will give that a shot.

Kent Bull01:07:32

That worked!

Kent Bull01:07:49

I freaking love Clojure. The REPL loves me back every time I use it. This is the language I am the most productive in.

2
👍 2
jdkealy15:07:17

If i had a start date/end date, and a "schedule" like {:monday {:start "1am", :end "2am"}} How could I generate a series of dates ?

jdkealy15:07:04

I see clj-time does something with sequences. But I don't want to work with joda-time, I'm using JUT's

jdkealy16:07:50

And then jave-time is also not compatible with java.util.date :man-facepalming:

lukasz16:07:14

You don't want to use either joda or java.util.date

jdkealy16:07:05

I'm using datomic is the thing

lukasz16:07:11

that's fine

jdkealy16:07:19

Ok, what should i use then ?

lukasz16:07:48

you can use the java time wrappers (like Tick or java-time) first to generate an interval, slice it, and then convert instants to java.util.Date as the last step

jdkealy16:07:30

ok that makes sense. I just installed tick

lukasz16:07:12

let me dig out the code, I had to do this not long ago

lukasz16:07:56

hm, can't find it haha, looks like I moved to a different approach. It doesn't matter - what you need is to use https://cljdoc.org/d/tick/tick/0.4.30-alpha/api/tick.interval and once you have sub-divisions, pick the start and process the results

jdkealy16:07:59

so... like... Generate the weeks array ? And then per week, set it to Monday and the start time ?

jdkealy16:07:24

(def dates  (let [intvl (t.i/bounds (t/year))]
              (t/range
               (t/beginning intvl)
               (t/end intvl)
               (t/new-period 1 :weeks))))

(def schedule {:MONDAY {:start "1am" :end "2am"}
               :TUESDAY {:start "1am" :end "2am"}})

(->> dates
     (map (fn [date]
            (->> schedule
                 (map (fn [[k {:keys [start end]}]]
                        (let [day (case k
                                    :MONDAY (set-date-to-monday date)
                                    :TUESDAY (set-date-to-tuesday date)
                                    ( "not finished"))]
                          [{:start (set-time day start)
                            :end (set-time day end)}])))
                 (filter identity)))))

lukasz16:07:41

Something like that yeah

jdkealy16:07:44

just need to create (set-date-to-monday date)

lukasz16:07:25

Just watch out for timezones - "Monday 1am" means many things

jdkealy16:07:43

right... i'll know the intended timezone

jdkealy16:07:59

i'll POC this in utc then move on

jdkealy16:07:33

How would you go about setting the date to "monday's date"

jdkealy16:07:28

adjust-into ?

lukasz16:07:34

You can start with an instant, adjust it to whatever point in time you need, and then generate an interval off that and so on

lukasz16:07:47

I should have asked this from the start: what are you trying to achieve?

jdkealy16:07:08

I want a start-date, end-date, schedule, and generate a list of instants

lukasz16:07:27

can you define "schedule" a bit more?

jdkealy16:07:27

ultimately, i'm scheduling classes for kids to attend for school

jdkealy16:07:42

so... i'll send a notification, kids join/educator joins

jdkealy16:07:06

in datomic, i poll "what's coming in the next minute" -> send them all notifications

jdkealy16:07:24

so... a single course could have 90 "sessions"

jdkealy16:07:29

or classes

jdkealy16:07:12

start => 2000-01-01 end => 2001-01-01 schedule {"monday" {"start "1pm" "end" "2pm"}}

lukasz16:07:05

gotcha, I built this somewhat differently: I use cron-utils to build a background scheduler that (among many other things) checks every 5m if there are any upcoming events in the meeting database and handles that (15m-before-start reminder etc). Meetings are created off bounds and do not depend on the scheduler per-se, they just have recurrence information baked in and the scheduler takes care of creating them ahead of time, finding next time slot and so on. So you could define your events in terms of cron expressions, so you don't really have to do the date time math yourself for the most part https://github.com/jmrozanec/cron-utils

lukasz16:07:39

Although there's many caveats, you're building something slightly different and you might need to drop down to the java.time.* stuff directly to get the most flexible approach, I started with tick but moved off it to have more control

🙏 2
jdkealy18:07:40

Is this the following even possible. Someone says start_time "01/01" end time "02/01" I know they're in New York "America/NEW_YORK"

jdkealy18:07:32

i get the range of dates at midnight, and then parse the dates in yyyy-mm-dd and then i concatinate "hh-mm" formatted in NY time

jdkealy18:07:32

and then parse the concatinated result... i guess that won't work because unless my range of yyyy-mm-dd dates are guaranteed to be the right date....

jdkealy18:07:56

UTC at midnight will be the day before for like half the world

lukasz18:07:29

Kinda: you figure out start of the day in their TZ, built a seq of timestamps until end of the day in TZ, and then convert all of them to instants

jdkealy18:07:42

timezones melt my brain

jdkealy18:07:11

(def dates  (let [intvl (t.i/bounds (t/year))]
              (t/range
               (t/beginning (java.util.Date.))
               (t/end intvl)
               (t/new-period 1 :weeks))))

jdkealy18:07:01

i hope maybe adjust-date allows a timezone

jdkealy18:07:13

e.g. tuesday in new york

lukasz18:07:05

Always stick to the following and it works out: • always store UTC timestamps only plus TZ info for all users • Use timezone info to get zoned data times only for calculations and always convert back to UTC • send only UTC to the UI and display zoned dates time there • Accept only UTC timestamps or explicitly send zoned date times although I don’t advise the latter approach

jdkealy18:07:15

yes i'm doing all that

jdkealy18:07:46

a user though enters they want their class at 1PM. They're thinking local time

lukasz18:07:57

http://everytimezone.com is invaluable for this btw

jdkealy18:07:07

i will be saving it as UTC, and i save "1PM" and i save "America/NEW_YORK"

lukasz16:07:26

That should be a sound approach, although just saving the UTC instant + timezone is usually sufficient

lukasz16:07:18

btw, JDK has a TimeZone class so you can get a standard list of all available timezones with offsets and such. One caveat is that you have to start taking care of updating the timezone database, because it changes every now and then

lukasz16:07:39

there's a tool that updates the JDK tz db version

vemv20:07:14

Was there a precise pred for checking if something is a list or a cons?

vemv20:07:55

and not a lazy sequence, much less a vector

p-himik20:07:29

Pretty sure there's nothing built-in. But perhaps you can check whether something is an instance of clojure.lang.ASeq.

vemv20:07:31

thanks! 🍻

👍 2
phronmophobic20:07:21

for your purposes, is there a difference between a fully realized lazy sequence and a list?

vemv20:07:39

maybe not, although I'll be happy with

(or (list? form) (instance? Cons form))
most of all for conveying programmer intent

phronmophobic20:07:50

what's the intent?

vemv20:07:08

dealing with source code, which is never read lazily

phronmophobic20:07:33

Not sure I follow. Clojure evaluates forms, which may or may not be lazy. The reader is separate. I don't think the builtin clojure reader every produces lazy sequences, but you could have other readers or non-reader sources for producing code to evaluate (eg. macros).

vemv20:07:06

I'm only dealing with the "read" phase in this context, I can be certain forms are just lists/cons at this stage (please let's leave the convo at that 🙏)

phronmophobic20:07:28

Ok, I was hoping to maybe learn something new. My guess is that seq? is the correct predicate, but it's unclear what the use case is.

vemv20:07:24

Why is the Thread metadata lost if I process it with the following defn? :thinking_face:

(defn macroexpanded-context [ns form]
  (->> form
       (walk/postwalk (fn [x]
                        (if (and (list? x)
                                 (-> x first symbol?)
                                 (contains? #{#'clojure.core/->
                                              #'clojure.core/->>
                                              #'clojure.core/..
                                              #'clojure.core/doto}
                                            (->> x first (ns-resolve ns))))
                          (macroexpand-1 x)
                          x)))))

(comment
  (binding [*print-meta* true]
    (clojure.pprint/pprint (macroexpanded-context *ns*
                                                  '({:idx 3, :form '(-> x ^Thread (anything) __prefix__)})))))