Fork me on GitHub
#beginners
<
2019-04-10
>
ho0man05:04:47

Hi, How can I convert an instance of java.sql.Timestamp to a zoned date? —- I am using clojure.java-time

seancorfield06:04:40

user=> (java.sql.Timestamp/from (jt/instant))
#inst "2019-04-10T06:16:24.131160000-00:00"
user=> (-> *1 (jt/zoned-date-time "UTC"))
#object[java.time.ZonedDateTime 0x1805383 "2019-04-10T06:16:24.131160Z[UTC]"]
user=>     

seancorfield06:04:19

@ho0man I was missing the zone ID before. The above should work with whatever timezone you want to specify.

ho0man06:04:42

@seancorfield thanks a lot. I have another question though ... now that I have the ZonesDateTime ... how can I extract the date (is using jt/local-date correct to extract just the date) I am trying to select all records related to some event that occurred today

Lennart Buit06:04:00

there is also the ability to get the current zone id: (jt/zone-id)

seancorfield06:04:27

Just call local-date on it...

user=> (java.sql.Timestamp/from (jt/instant))
#inst "2019-04-10T06:22:53.533774000-00:00"
user=> (type *1)
java.sql.Timestamp
user=> (-> *2 (jt/zoned-date-time "America/New_York"))
#object[java.time.ZonedDateTime 0x106cd9c8 "2019-04-10T02:22:53.533774-04:00[America/New_York]"]
user=> (-> *1 (jt/local-date))
#object[java.time.LocalDate 0x77ce88c4 "2019-04-10"]
user=>  

seancorfield06:04:14

To be honest tho', if you're doing this in a database, I'd recommend keeping everything on UTC and sticking with instants.

ho0man06:04:13

It is stored as UTC timestamp in the DB, may it still cause any problem?

Lennart Buit06:04:27

I read a blog the other day why this is not always enough, but I cannot find it anymore 😢

Lennart Buit06:04:02

but most likely, storing just UTC, or UTC + Zone is enough. Only in particular cases it is not

seancorfield06:04:07

Yeah, if you need to store local event times because you need to operate on and display local event times, then using zoned or offset makes sense. That's not been the case for any app I've ever worked on, except for rare cases of location-specific events (but even that can be handled by UTC and zone in most cases). Timezones are hard is the bottom line here!

Lennart Buit06:04:31

yeah sorry, I am just providing a particular counter example ^^!

seancorfield06:04:19

Oh, no, definitely worth mentioning! This stuff is nasty. I hate having to deal with timezones!

seancorfield06:04:09

We're lucky that for the most part we only care about relative actions: when was someone last online relative to you, when did they like you, when did you purchase your 30 day membership etc.

seancorfield06:04:12

We don't need to care about someone in France attending an event in London that starts on a certain date at a certain local time 🙂 I have enough of that trying to deal with calling my mother every Monday at 5pm her time (I'm in California)!

Lennart Buit06:04:48

haha yeah, having the same timezone in most of europe is quite convenient

seancorfield06:04:24

I live in a country with four timezones, and not all parts of every state observe DST 🙂

seancorfield06:04:32

(my state just voted to allow the legislature to petition the federal government to stop observing DST -- yay!)

Lennart Buit06:04:14

yeah the EU is going to drop DST, but its up to its members to choose what tz to keep. The netherlands however, already is in an ill fitting timezone, so keeping DST all year is a terrible idea that probably will happen

Lennart Buit06:04:54

or — we have a different timezone than germany has, which is also a terrible idea. There are no winners in this timezone debate 😛

Lennart Buit06:04:30

this API is growing on me

seancorfield06:04:32

Avoid local date/times altogther.

seancorfield06:04:19

Truncate a timestamp to a date, via an instant

user=> (java.sql.Timestamp/from (jt/instant))
#inst "2019-04-10T06:28:37.100373000-00:00"
user=> (-> *1 (jt/instant) (jt/truncate-to :days))
#object[java.time.Instant 0x37fef327 "2019-04-10T00:00:00Z"]
user=>        

👏 1
Lennart Buit06:04:02

doesn’t that keep zone?

Lennart Buit06:04:17

(well not with instant’s, but with zoned-date-times)

Lennart Buit06:04:26

ah yeah, sorry!

seancorfield06:04:33

Avoid zoned date times, stay in UTC everywhere. Seriously.

seancorfield06:04:07

We have all our servers set to UTC and our database set to UTC. We do everything in UTC on the server, and only convert to local date/time for display. It's the only sane option.

👍 1
seancorfield06:04:20

(we have a global 24x7 customer base)

Lennart Buit06:04:21

I agree, I just wasn’t very awake just yet

orestis06:04:43

Unless you want to store “local” dates — i.e., this event will start when the clocks show 5:00pm at that specific city. Then a local date is more appropriate, I believe. I fuzzily remember reading about how in some cases UTC is not the best choice, and I think this use case is one of them.

seancorfield07:04:30

@orestis Yes, see the long thread from about half an hour ago 🙂

orestis07:04:07

Haha 😄 I recall someone mentioning that if you really want to deal with relative events, look into the iCal format RFC and just do that.

Nazral07:04:04

I imagine doing

(def global-conf {})

;; code that uses global-conf

(def -main [& args]
   (def global-conf (my-conf-builder-function args))
   ;; calling code
   )
is not the clojure way?

Nazral07:04:58

(I'm using compojure and I need the conf to be passed to functions handling the routes, that's why I resorted to this)

seancorfield07:04:25

Never put a def inside another function. Not idiomatic at all.

seancorfield07:04:03

With Ring/Compojure, you can use middleware to add configuration to the request hash map.

seancorfield07:04:27

In your -main, when you build the "application", wrap the handler in a middleware closure that includes your built configuration and assocs it into the request so that handlers can read it from that.

Nazral07:04:33

I don't think this applies to the websocket requests and event handling of sente

orestis08:04:49

If you really want global mutable state, then you should use an atom

orestis08:04:46

(def global-conf (atom {}))

(defn my-handler [...]
 (let [conf @global-conf]
  ...))

(defn -main [& args}
  (reset! global-conf (my-conf-build-function args)
  ...)

Nazral08:04:26

I'm trying to avoid atoms because it's only modified at startup (config file with default values vs command line options) but I think I found how to do it by digging into sente's source

Jamie Rumbelow09:04:20

Hi all! Q q about testing conventions. I’ve got a utils namespace with some smaller funcs I find handy. Should I use with-test to test them? Or should I use deftest in a tests.utils namespace? Which is more common / idiomatic?

Vikram10:04:34

Hi all, can anyone tell me how to start learning clojure openscad. Thanks

pithyless10:04:28

@jamie962 I would do the latter, but only because I never really reach for with-test.

pithyless10:04:54

But this raises an interesting question - when do people reach for with-test?

pithyless10:04:53

e.g. a random datapoint: GitHub search returns 1k code results for with-test, but 104k code results for deftest

Jamie Rumbelow08:04:47

That’s interesting – I guess the standard is to separate out tests from implementation. But for pure functions (with no tricky mocking or whatever) I see no reason why they couldn’t be coupled. Tests, when well written, are excellent documentation!

Gauthier Feuillen14:04:17

New to Clojure, looking for resources on how to use the REPL in the right way. Do you have any recommendations ?

hipster coder17:04:07

if you are coming from Vim, Spacemacs combines Vim with Emacs. So it helps you learn emacs in steps.

orestis19:04:00

Have you read the REPL guide on the CLojure website?

manutter5114:04:25

You can also get some hits on the search phrase “repl-driven development”

victorb16:04:43

https://purelyfunctional.tv/courses/repl-driven-development-in-clojure/ by @ericnormand is very nice too (although require a subscription to see the full series [and I haven't actually watched the full one, just bunch of snippets])

adam17:04:04

I am planning to use Compojure for a new project, which version of Java should I go with 8 or 11?

alexmiller18:04:39

Unless you have some reason to do otherwise I’d use openjdk Java 11

ghadi18:04:34

if you get WARNING: Reflective Access stuff in your log, I'd talk to the maintainers of the projects to make sure they're not doing anything naughty

jaihindhreddy18:04:19

Newb question: Can someone please succinctly explain the difference b/w the following: Java, JVM, JDK, JRE. And/or point me to resources I should study to learn more. Also, what's open in openjdk?

ghadi18:04:31

.... I will try

ghadi18:04:25

Java is the programming language, and informally the associated runtime. This term probably depends on context JVM is the runtime. It runs your application from .class files and .jars full of them. It manages memory, loads code, optimizes the code dynamically into machine code. Clojure compiles to .class files and dynamically loads it into the JVM. The JDK is the "Java Development Kit". It includes the java language compiler, the JVM, and a ton of tooling. The JRE is the "java runtime environment" -- just the JVM typically. You'd distribute your application to end users with the JRE if it's pre-compiled, otherwise you'd tell users to install the JDK.

👏 2
👍 1
ghadi18:04:08

the open in OpenJDK is a reference to the fact that the source code is public under the GPL license

jaihindhreddy18:04:41

Got it. Thanks a lot Ghadi!

ghadi18:04:46

my pleasure

jaihindhreddy18:04:57

I just remembered your talk is in my watch later. Java made somewhat simple if I remember correctly. I'll go watch it. Thanks for the talk too!!

jaihindhreddy18:04:33

So when I hear about Java being very stable, the JVM promises to run any old dusty JAR (artifact) but the java language may break and not allow dusty code to create the artifact...

alexmiller18:04:24

in general, that's rare.

👍 1
jaihindhreddy18:04:31

And if so, Clojure's promise of compatibility only reaches Clojure's constructs. If I user some Java thing with interop, and Java decides to break it, I may be broken

alexmiller18:04:50

Java breaks things less frequently than Clojure

alexmiller18:04:13

you can take Clojure 1.0 stuff and run it on Java 11 just fine

alexmiller18:04:55

the key thing as of Java 11 is that if you want to use the Oracle version for commercial use, you must purchase a license from Oracle, which was not previously true

alexmiller18:04:15

but because Java is GPL and openjdk exists, you can use the openjdk version for free

ghadi18:04:45

that being said, Oracle open sourced all of the previously closed tools during the Java 11 release

alexmiller18:04:46

and there are now multiple vendors helping to provide support and bug fixes for this and older releases

ghadi18:04:03

so you'd be paying oracle not for enhanced features, but enhanced support

👍 1
ghadi18:04:21

Amazon Corretto 8/11 is a distribution of Java 8/11 that has longevity and security patching, if you're into that

alexmiller18:04:09

(you should be into that :)

🙃 1
jaihindhreddy18:04:28

I'm aware of only two things that may be considered as Clojure breaking something. Numerics at around 1.3, and core async buffer semantics (subtly because if a buffer isn't full it must accept any number of things) when transducers were introduced.

alexmiller18:04:00

well that one is more bending :)

1
jaihindhreddy18:04:05

Did Clojure break more stuff? I know a bunch of deprecations exist.

alexmiller18:04:20

but there have been a handful of other breaking things throughout the years, but mostly not major things

ghadi18:04:42

Clojure has a good track record in that dept

alexmiller18:04:01

we also don't make the same level of binary compatibility promises that Java does

alexmiller18:04:14

if you happen to AOT your code for example

ghadi18:04:21

I really want resultset-seq and bean to be removed from core... ¯\(ツ)

1
alexmiller18:04:42

although we do try to be very careful in any changes that might break aot-compiled code

👍 1
alexmiller18:04:29

and I think in general, those kind of breaks have also been rare (I can't actually think of one off the top of my head)

jaihindhreddy18:04:13

All I can think of are, as you said, bendings 🙂

jaihindhreddy18:04:55

Any non interop Clojure (pure Clojure, if you will) still compiles and runs fine.

alexmiller18:04:28

part of that is Clojure's intentional under-specification of the core api to allow us some room for growth :)

alexmiller18:04:49

so we can add arities or polymorphically handle a broader set of things

alexmiller18:04:57

and we've done a lot of that

jaihindhreddy18:04:15

I loved it when so many fns got transducer returning arities.

alexmiller18:04:37

yeah, transducers was purely additive from an api perspective

2
💯 2
jaihindhreddy18:04:59

It was awesome that all those extra arities weren't used up for weak reasons like syntactic sugar.

jaihindhreddy18:04:18

Which accommodated transducers beautifully.

Robert Nikander20:04:18

Is there a shorter way to say this: (fn [a b] (= (:id a) (:id b)))? It almost looks like (comp = :id) but not quite.

ballpark20:04:08

#(= (:id %1) (:id %2))?

👍 1
alexmiller20:04:17

You could map :id, then apply = for a variadic version

👍 2
alexmiller20:04:28

Anytime I write code that works with exactly 2 things, I view it with suspicion

alexmiller20:04:05

Writing it for N, or writing it for 1 and using the seq lib are usually better

ballpark20:04:31

this might be what Alex is proposing (->> some-seq (map :id) (apply =))

alexmiller20:04:36

(fn [& xs] (->> xs (map :id) (apply =)))

alexmiller20:04:53

in fn form, but yep

Robert Nikander20:04:51

In some situations I like that, but in my current code I feel like want to say "compare these two things by ID", and if I write the map+apply it makes the code harder to read.

Lennart Buit20:04:44

you can write (fn [{id-a :id} {id-b :id}] (= id-a id-b)) if you really want to

Lennart Buit20:04:42

but I personally don’t think it becomes much clearer

alexmiller21:04:14

you could probably generify this pattern to something like

(defn =-by [pred & xs]
  (->> xs (map pred) (apply =)))

alexmiller21:04:35

(=-by :id a b)

👍 1