Fork me on GitHub
#beginners
<
2022-04-30
>
Jim Strieter01:04:53

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?

Bob B01:04:57

zone-id isn't used, so I'd guess it's a time zone difference

Jon Boone01:04:55

what does (int (/ (.getTime my-date) 1000)) evaluate to?

Jon Boone01:04:39

more, importantly, I suppose, is what does (.getTime my-date) evaluate to...

seancorfield02:04:59

@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 "java.text.SimpleDateFormat@c166e9a"]
user=> (.parse *1 "19700101 00:00")
#inst "1970-01-01T08:00:00.000-00:00"
user=> 

seancorfield02:04:36

Note the T08 for the hours.

user=> (.getTime *1)
28800000
user=> (int (/ *1 1000))
28800
I'm guessing you're in EDT right now?

seancorfield02:04:57

(18000 is 5 hours, 28800 is 8 hours)

Jim Strieter11:04:34

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.

Jim Strieter11:04:55

I found the problem. I forgot to use the zone-id input in my function. Thanks for reading everybody!

Brandon Stubbs16:04:56

(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))

seancorfield18:04:09

"I found the problem. I forgot to use the zone-id input in my function. Thanks for reading everybody!" -- @U013JFLRFS8 gets the debugging prize! duckie

πŸ™Œ 1
Jim Strieter19:04:35

@U04V70XH6 damn right πŸ˜‚

Jon Boone03:04:35

Hi there! I've seen references to something called autoquoting by a number of Clojurists. What is that exactly?

hiredman03:04:31

Are you sure you didn't hear auto-gensym?

🧡 3
hiredman03:04:23

People definitely refer to syntax quotes gensyming as that sometimes

🧡 3
hiredman04:04:59

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)

🧡 3
Jon Boone10:04:42

That's interesting β€” my experience has been the opposite. Never heard the term auto quoting outside of Clojure discourse…

noisesmith14:05:57

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

Ho0man13:04:23

Hi everyone, How can I spawn a thread that prevents JVM from shutting down even when the main thread exits ?

Bob B14:04:57

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).

sova-soars-the-sora20:04:32

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)

sova-soars-the-sora20:04:28

β†’ (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

sova-soars-the-sora20:04:53

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

phronmophobic20:04:45

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?

sova-soars-the-sora20:04:27

i think 0+ 1 and then 1+0 ... not null πŸ˜…

phronmophobic20:04:56

Is there a way to check?

phronmophobic20:04:50

What is the value of (:result 1)?

sova-soars-the-sora20:04:21

it's (:result {:result 1}) non?

sova-soars-the-sora20:04:49

under the impression each map in the vector becomes an input

sova-soars-the-sora20:04:58

I am missing something fundamental πŸ˜…

phronmophobic20:04:15

there's fancier ways of doing it, but have you tried sprinkling in some print statements?

sova-soars-the-sora20:04:44

internal screaming at a 2.8-3.1 / 10

sova-soars-the-sora20:04:43

What is bad about

(reduce 
  #(+ (:result %1) (:result %2))   
  0 
  [{:result 0} 
   {:result 1} 
   {:result 2}])

phronmophobic20:04:18

have you tried printing the arguments to your reducing function?

phronmophobic20:04:47

what does (:result 0) evaluate to?

sova-soars-the-sora20:04:24

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

sova-soars-the-sora20:04:57

(reduce (fn [r1 r2] (+ (if (keyword? r1) (:result r1) r1) (:result r2))) 0 rft)
πŸ˜…

sova-soars-the-sora20:04:13

if it's a keyword, grab the val under the key, otherwise just grab the presumed-int

sova-soars-the-sora20:04:22

thanks πŸ˜„ it was making me cranky

phronmophobic20:04:48

pretty sure the keyword? branch doesn't do anything

1
phronmophobic20:04:09

(reduce (fn [r1 r2]
          (+ r1 (:result r2)))
        0
        rft)

phronmophobic20:04:54

which I would improve by using slightly better names:

(reduce (fn [cnt m]
          (+ cnt (:result m)))
        0
        rft)

phronmophobic20:04:49

As food for thought, you could also write it more directly with transduce:

(transduce (map :result) + rft)

1
☝️ 1
sova-soars-the-sora04:05:37

Thank you, that is a lot clearer now, that one of the arguments is the accumulator. I was not appreciating that.

Ben Sless05:05:48

The 2 arg arity of reduce is evil, try to always provide init value if you can

1