This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-10-02
Channels
- # announcements (12)
- # asami (5)
- # aws (3)
- # babashka (12)
- # beginners (86)
- # calva (14)
- # chlorine-clover (3)
- # cider (13)
- # clara (8)
- # cljdoc (1)
- # cljfx (2)
- # cljsrn (1)
- # clojure (69)
- # clojure-berlin (6)
- # clojure-czech (14)
- # clojure-dev (17)
- # clojure-europe (76)
- # clojure-france (14)
- # clojure-nl (43)
- # clojure-norway (6)
- # clojure-spec (7)
- # clojure-uk (13)
- # clojurescript (4)
- # code-reviews (1)
- # conjure (16)
- # cursive (2)
- # data-science (3)
- # datascript (1)
- # datomic (41)
- # events (4)
- # fulcro (9)
- # hugsql (3)
- # instaparse (5)
- # jobs (3)
- # malli (1)
- # mid-cities-meetup (1)
- # nrepl (22)
- # off-topic (25)
- # onyx (1)
- # pedestal (3)
- # remote-jobs (3)
- # shadow-cljs (61)
- # sql (22)
- # xtdb (12)
Is it possible to pull all attributes, but with a default? I’m imagining something like:
(pull [(* :default :no-value)] …
I don't see how that could be possible. "*" means all attributes that an entity has so there can't be a default.
(let [attributes (d/q '[:find [?a ...]
:where
[?e ?a _]]
db)
pattern (mapv (fn [attribute]
`(~attribute :default :no-value))
attributes)]
(d/q `[:find (pull $ ~pattern ?e)
:in $
:where
[?e _ _]]
db))
So I have the following query:
{:query
{:find [?e],
:in [$ ?string-val-0],
:where
[(or-join
[?e]
(and
[?e :exception/message ?message-0]
[(.contains ?message-0 ?string-val-0)])
(and
[?e :exception/message ?explanation-0]
[?explanation-0 :message/explanation ?explanation-val-0]
[(.contains ?message-0 ?string-val-0)]))]},
:args
[#object[compute.datomic_client_memdb.core.LocalDb 0x2a589f86 "compute.datomic_client_memdb.core.LocalDb@2a589f86"]
"abc"]}
But I'm getting Execution error (Exceptions$IllegalArgumentExceptionInfo) at datomic.error/arg (error.clj:57).
:db.error/insufficient-binding [?string-val-0] not bound in expression clause: [(.contains ?message-0 ?string-val-0)]
, and I'm not sure why
If you want ?string-val-0
to unify the outer clause you’ll need to include it in the rules-vars
vector: (or-join [?e ?string-val-0] …)
I'm trying to figure out how to format db.type/instant values, for display in a UI. Using clojure.java-time as follows:
(:require [java-time :as t])
evaluating
(t/format #inst "2020-09-26T23:08:27.619-00:00")
returns "Sun Sep 27 01:08:27 CEST 2020"
but if I add a custom format
(t/format "dd/MM/yyyy" #inst "2020-09-26T23:08:27.619-00:00")
I get the error
Execution error (ClassCastException) at java-time.format/format (format.clj:50).
java.util.Date cannot be cast to java.time.temporal.TemporalAccessor
(t/instant #inst "2020-09-26T23:08:27.619-00:00")
=> #time/instant "2020-09-26T23:08:27.619Z"
(t/format "yyyy/MM/dd" (t/instant #inst "2020-09-26T23:08:27.619-00:00"))
=> Execution error (UnsupportedTemporalTypeException) at java.time.Instant/getLong (Instant.java:603).
Unsupported field: YearOfEra
the clojure.java-time docs for t/instant say this function "Creates an Instant" https://cljdoc.org/d/clojure.java-time/clojure.java-time/0.3.2/api/java-time.temporal#instant
(t/instant? (.toInstant #inst "2020-09-26T23:08:27.619-00:00"))
=> true
(t/instant? (t/instant #inst "2020-09-26T23:08:27.619-00:00"))
=> true
This works: (t/format "
=> "2015.09.28"
but I can't find a way to convert a datomic db.type/instant to a zoned-date-time.
user=> (t/format "dd/MM/yyyy" (t/zoned-date-time #inst "2020-09-26T23:08:27.619-00:00" (t/zone-id "UTC")))
"26/09/2020"
user=>
(or whatever TZ you need there)
Although if you're dealing with #inst
which I believe are just regular java.util.Date
objects, this should work (without clojure.java-time
at all):
user=> (let [f (java.text.SimpleDateFormat. "dd/MM/yyyy")]
(.format f #inst "2020-09-26T23:08:27.619-00:00"))
"26/09/2020"
user=>
Yup, Datomic docs say it's just a java.util.Date
:
:db.type/instant instant in time java.util.Date #inst "2017-09-16T11:43:32.450-00:00"
@U04V70XH6 Thanks very much! I've confirmed that both approaches work as expected with an #inst returned from datomic.
I've learned a lot here, both by dipping my toes into the clojure.java-time
and tick
libraries, and getting a more practical sense of how java interop works through your example.
@U078GPYL8 I meant something like this (sorry, was on a phone earlier):
(let [d #inst"2020-10-03T12:18:02.445-00:00"
f (-> (java.time.format.DateTimeFormatter/ofPattern "dd/MM/yyyy")
(.withZone (java.time.ZoneId/systemDefault)))]
(.format f (.toInstant d)))
I avoid java.text.SimpleDateFormat because it’s the “old” way and it’s not thread-safe
I think what sean posted is nearly the equivalent, except he coerces to a zoned date time instead of specifying the zone in the formatter
@U09R86PA4 I see what you originally meant evaluating
(let [d #inst"2020-10-03T12:18:02.445-00:00"
f (-> (java.time.format.DateTimeFormatter/ofPattern "dd/MM/yyyy")
(.withZone (java.time.ZoneId/systemDefault)))]
(.format f d))
In what type of use case would the fact that SimpleDateFormat is not thread safe produce an unexpected result, particularly in the context of a web application?
The oldest is Java.util.date objects. The newest is Java.time.*, which represents instants as Java.time.Instant objects instead.
Yup, going via Java Time is definitely the safest route and the best set of APIs to learn. At work, over the past decade we've gone from java.util.Date
to date-clj
(date arithmetic for that old Date
type), to clj-time
(wrapping Joda Time), to Java Time (with clojure.java-time
in some parts of the code and plain interop in a lot of places). Converting java.util.Date
to java.time.Instant
and doing everything in Java Time is a bit painful/verbose, but you can write utility functions for stuff you need frequently to hide that interop/verbosity.