This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-30
Channels
- # announcements (5)
- # babashka (9)
- # beginners (48)
- # calva (300)
- # clj-kondo (9)
- # clojure (44)
- # clojure-austin (2)
- # clojure-europe (14)
- # clojure-uk (4)
- # clojurescript (1)
- # conjure (2)
- # datascript (3)
- # datomic (8)
- # exercism (5)
- # fulcro (1)
- # luminus (4)
- # music (1)
- # off-topic (12)
- # pathom (2)
- # rdf (18)
- # react (8)
- # sci (78)
- # shadow-cljs (12)
- # spacemacs (4)
- # tools-build (5)
- # tools-deps (26)
- # vim (4)
- # xtdb (8)
Hi, I am trying to convert a date string to epoch time like this:
(defn yyyyMMddHHmm-to-epoch
[datestr zone-id]
(let [my-date-obj (new SimpleDateFormat "yyyyMMdd HH:mm")
my-date (.parse my-date-obj datestr)]
;; Epoch time is milliseconds by default in Java so we have to divide:
(int (/ (.getTime my-date) 1000))))
Here is a unit test:
(deftest test-yyyyMMddHHmm-to-epoch
(testing "yyyyMMddHHmm-to-epoch failed"
(is (= 0 (yyyyMMddHHmm-to-epoch "19700101 00:00" "Etc/UTC")))))
This test is failing, with this message:
FAIL in (test-yyyyMMddHHmm-to-epoch) (core_test.clj:98)
yyyyMMddHHmm-to-epoch failed
expected: (= 0 (yyyyMMddHHmm-to-epoch "19700101 00:00" "Etc/UTC"))
actual: (not (= 0 18000))
It is strange to me that my function is returning 18000 seconds have elapsed as of midnight, Jan 1, 1970.
Why is this happening?@U014Z9N3UTS As @U013JFLRFS8 says, it's a timezone issue. I'm West Coast:
user=> (import '(java.text SimpleDateFormat))
java.text.SimpleDateFormat
user=> (new SimpleDateFormat "yyyyMMdd HH:mm")
#object[java.text.SimpleDateFormat 0x5bca7664 "[email protected]"]
user=> (.parse *1 "19700101 00:00")
#inst "1970-01-01T08:00:00.000-00:00"
user=>
Note the T08
for the hours.
user=> (.getTime *1)
28800000
user=> (int (/ *1 1000))
28800
I'm guessing you're in EDT right now?(18000 is 5 hours, 28800 is 8 hours)
If you look in the test, you can see that it specifies the UTC timezone. The Unix epoch is defined in UTC, which is why I'm having a hard time finding the problem.
I found the problem. I forgot to use the zone-id input in my function. Thanks for reading everybody!
Also use java 8's java.util.time.*
https://www.baeldung.com/migrating-to-java-8-date-time-api
(import '(java.time.format DateTimeFormatter)
'(java.time LocalDateTime ZoneOffset))
(def formatter (DateTimeFormatter/ofPattern "yyyyMMdd HH:mm"))
(-> (LocalDateTime/parse "19700101 00:00" formatter)
(.toInstant (ZoneOffset/UTC))
(.toEpochMilli)
(/ 1000))
"I found the problem. I forgot to use the zone-id input in my function. Thanks for reading everybody!" -- @U013JFLRFS8 gets the debugging prize!
@U04V70XH6 damn right 😂
Hi there! I've seen references to something called autoquoting by a number of Clojurists. What is that exactly?
I've maybe seen auto quoting in a more general lisp context used to describe things that evalute to themselves (like numbers, keywords, strings, etc)
That's interesting — my experience has been the opposite. Never heard the term auto quoting outside of Clojure discourse…
I've been engaged with clojure for over a decade and have no idea what auto-quoting would be, definitely have not heard it mentioned
Hi everyone, How can I spawn a thread that prevents JVM from shutting down even when the main thread exits ?
In general, you want the thread to be non-daemon. Taking selected bits from the Thread javadoc: > ... The Java Virtual Machine continues to execute threads until either of the following occurs: > ... > • All threads that are not daemon threads have died... There are several ways to accomplish this, from using the Thread constructor via raw interop to using Clojure functions that start/use non-daemon threads (future or pmap, for example).
Thanks a lot @U013JFLRFS8
Beginner question about reduce
(def rft
[{:artefact-id 2
:seen-date 92139000
:result 1}
{:artefact-id 5
:seen-date 92140707
:result 0}
{:artefact-id 7
:seen-date 92141627
:result 1}
{:artefact-id 3
:seen-date 92141333
:result 0}])
(map :result rft)
→ (1 0 1 0)
(apply + (map :result rft))
→ 2 🆒
but
(reduce #(+ (:result %1) (:result %2)) rft)
Execution error (NullPointerException) at user/eval9$fn (REPL:1).
null
How can I achieve addition of the :result keys from this vector of maps using reduce
? I think my function takes 2 args o_O
1. what is the value of the accumulator for your reduce function on the first call? 2. what is the value of the accumulator on the second call?
i think 0+ 1 and then
1+0
... not null
😅
Is there a way to check?
What is the value of (:result 1)
?
it's (:result {:result 1})
non?
under the impression each map in the vector becomes an input
I am missing something fundamental 😅
there's fancier ways of doing it, but have you tried sprinkling in some print statements?
internal screaming at a 2.8-3.1 / 10
What is bad about
(reduce
#(+ (:result %1) (:result %2))
0
[{:result 0}
{:result 1}
{:result 2}])
have you tried printing the arguments to your reducing function?
what does (:result 0)
evaluate to?
The prn is helpful...
(reduce
#(prn %1 %2)
0
[{:result 0}
{:result 1}
{:result 2}])
0 {:result 0}
nil {:result 1}
nil {:result 2}
nil
(reduce (fn [r1 r2] (+ (if (keyword? r1) (:result r1) r1) (:result r2))) 0 rft)
😅if it's a keyword, grab the val under the key, otherwise just grab the presumed-int
thanks 😄 it was making me cranky
(reduce (fn [r1 r2]
(+ r1 (:result r2)))
0
rft)
which I would improve by using slightly better names:
(reduce (fn [cnt m]
(+ cnt (:result m)))
0
rft)
As food for thought, you could also write it more directly with transduce
:
(transduce (map :result) + rft)
Thank you, that is a lot clearer now, that one of the arguments is the accumulator. I was not appreciating that.