dm3 / clojure.java-time Goto Github PK
View Code? Open in Web Editor NEWJava 8 Date-Time API for Clojure
License: MIT License
Java 8 Date-Time API for Clojure
License: MIT License
I want to process a timeseries with monthly labels, so something like "2012-10" etc, but parser seems unhappy with this. I understand why, but it's pretty impractical.
user> (local-date-time "MM/yyyy" "09/2015")
DateTimeException Unable to obtain LocalDate from TemporalAccessor: {MonthOfYear=9, Year=2015},IS\
O of type java.time.format.Parsed java.time.LocalDate.from (LocalDate.java:368)
user> (local-date 2015 10)
#object[java.time.LocalDate 0x6a08b281 "2015-10-01"
While local-time
can be compared using after?
, local-date
doesn't have the required extension at this point. It'd be more intuitive (and useful) if local-date
could be similarly compared.
I can put up a PR if you're okay with that.
According to the threethen javadoc an interval is start inclusive and the end exclusive.
.
The javadoc of the isBefore
and isAfter
reflect this:
Since intervals do not include their end points, this will return true if the instant equals the end of the interval.
Using java-time however, this is not the case:
i
=> #object[org.threeten.extra.Interval 0x17e871bf "2018-01-01T00:00:00Z/2019-01-01T00:00:00Z"]
i2
=> #object[org.threeten.extra.Interval 0x51897443 "2019-01-01T00:00:00Z/2020-01-01T00:00:00Z"]
(.isBefore i i2)
=> true
(java-time/before? i i2)
=> false
The issue is a custom impl for single-before?
and single-after?
:
clojure.java-time/src/java_time/interval.clj
Lines 112 to 118 in 494e181
and can be mitigated by evalling
(extend-type Interval
jt.c/Ordered
(single-before? [i o] (.isBefore i o))
(single-after? [i o] (.isAfter i o)))
Would it be possible to add support for the org.threeteen.extra.scale.TaiInstant
and conversion between it and the UTC
time basis? The assumption would be that the user would have added the threeteen-extra library to the classpath.
Consider the following REPL session, in which version 0.3.2
of the library is being used (as per the deps.edn guide here).
(import java.time.temporal.ChronoField)
(import java.time.temporal.Temporal)
(def my-local-time (t/local-time 1 12 13 456000000))
(t/sql-time my-local-time)
#inst "1970-01-01T07:12:13.000-00:00"
Notice that the millisecond portion (456
) is lost. In principle, though, it is possible to build the java.sql.Time
instance to have that information:
(let [millis-of-day (.get my-local-time ChronoField/MILLI_OF_DAY)]
(java.sql.Time. millis-of-day))
#inst "1970-01-01T01:12:13.456-00:00"
The same problem occurs in reverse as well:
(def my-sql-time
(let [millis-of-day (.get my-local-time ChronoField/MILLI_OF_DAY)]
(java.sql.Time. millis-of-day)))
(t/local-time my-sql-time)
#object[java.time.LocalTime 0xda22aa "19:12:13"]
Again, it's possible to preserve that information (probably more elegantly than this):
(import java.time.LocalTime)
(LocalTime/ofNanoOfDay (* 1000000 (.getTime my-sql-time)))
#object[java.time.LocalTime 0x10d98940 "01:12:13.456"]
I have some code that looks like:
(for [[newer older] (partition 2 1 (iterate dec-period least_recent))
:let [_ (assert (instance? java.util.Date newer))
_ (assert (instance? java.util.Date older))]
:while (jt/after? (jt/instant newer)
(jt/instant oldest-message-date))]
[:least_recent #{newer older}])
And every once in a while when running my tests a get a stacktrace(sorry about the non-standard formatting) like
ws.messaging.migration/conversation-migration-information/iter/fn migration.clj: 242
java-time.temporal/instant temporal.clj: 350
java-time.graph/conversion-fn graph.clj: 316
java-time.potemkin.util/fast-memoize/fn util.clj: 52
java-time.graph/fn graph.clj: 301
java-time.graph/has-source-type? graph.clj: 281
java-time.graph/has-source-type?/contains-src-types? graph.clj: 279
clojure.core/some core.clj: 2701
java-time.graph/has-source-type?/contains-src-types?/fn graph.clj: 279
java-time.potemkin.util/fast-memoize/fn util.clj: 50
java-time.graph/fn graph.clj: 71
java-time.graph/assignable-type? graph.clj: 61
java.lang.Class.isAssignableFrom Class.java
java.lang.NullPointerException:
where line 242 is the (jt/after? ....)
line
The asserts are something I added in because I assumed at first I was somehow passing in nils, but they never fail.
Enhancement request: if would be nice to be able to do the equivalent of:
myDateValue.format(DateTimeFormater.ofLocalizedDate(FormatStyle.FULL))
i.e. to display dates and times in the default format for the current locale. Obviously this can be done quite easily with Java interop so not a big deal.
(the same applies to ofLocalizedTime
and ofLocalizedDateTime
)
DISCALIMER: This is probably a limitation of java.time
. But due to my limited experience with Java I cannot say for sure.
Reading documentation about ISO 8601 (specifically time zone offset) it seems the following 3 are valid string representations of dates:
2020-02-27T15:47:30.706+0100
2020-02-27T15:47:30.706+01:00
2020-02-27T14:47:30.706Z
For a real world use case the above formats will also be accepted during JSON Schema validation with string properties using the format date-time
.
My problem is that I can't seem to find a way for clojure.java-time
to accept all 3 variants without pre-processing of some kind.
I.e. giving the date string without :
in offset causes zoned-date-time
to throw and exception:
(zoned-date-time "2020-02-27T15:47:30.706+0100")
Execution error (DateTimeParseException) at java.time.format.DateTimeFormatter/parseResolved0 (DateTimeFormatter.java:2049).
Text '2020-02-27T15:47:30.706+0100' could not be parsed, unparsed text found at index 26
When providing a specific parsing format the problem is turned upside down (now date strings with :
causes exceptions to be thrown):
(zoned-date-time "y-M-d'T'H:m:s.SSSX" "2020-02-27T15:47:30.706+01:00")
Execution error (DateTimeParseException) at java.time.format.DateTimeFormatter/parseResolved0 (DateTimeFormatter.java:2049).
Text '2020-02-27T15:47:30.706+01:00' could not be parsed, unparsed text found at index 26
Another downside of having to specify the parsing format is that the length of "fraction of a second" seems to be fixed.
(defn conversion!
([from to f] (conversion! from to f 1))
([from-type-vec to-type-vec f cost]
(let [from (g/types (to-seq from-type-vec))
tos (combinations (to-seq to-type-vec) f cost)]
(doseq [[f to cost] tos]
(swap! graph
(fn [g]
(if-let [existing (g/get-conversion g from to)]
(when *fail-on-duplicate-conversion?*
(throw (ex-info (format "Conversion %s -> %s already exists: %s!" from to existing)
{:from from, :to to, :existing existing})))
(let [f (wrap-validation from to f)]
(g/assoc-conversion g from to f cost)))))))))
should be:
(defn conversion!
([from to f] (conversion! from to f 1))
([from-type-vec to-type-vec f cost]
(let [from (g/types (to-seq from-type-vec))
tos (combinations (to-seq to-type-vec) f cost)]
(doseq [[f to cost] tos]
(swap! graph
(fn [g]
(if-let [existing (g/get-conversion g from to)]
(if *fail-on-duplicate-conversion?*
(throw (ex-info (format "Conversion %s -> %s already exists: %s!" from to existing)
{:from from, :to to, :existing existing}))
g)
(let [f (wrap-validation from to f)]
(g/assoc-conversion g from to f cost)))))))))
There are nice existing after?
and before?
functions.
How do you feel about on-or-after?
or on-or-before?
? These are probably most useful for dates, not datetimes.
I think i'm confused on the usage... there is no way this could be a real bug.
I want a function that translates a date in string format from "yyyy-MM-dd'T'HH:mm:ss" format to "MM/dd/YYYY hh:mm:ss a" format.
Here's my function:
(require '[java-time :as jt])
(defn change-ds-format [in-ds]
{:pre [(string? in-ds )]
:post [(string? % )]}
(let [input-format "yyyy-MM-dd'T'HH:mm:ss"
output-format "MM/dd/YYYY hh:mm:ss a"]
(->> in-ds
(jt/local-date-time input-format)
(jt/format output-format))))
I have no idea why this pushed the year to 2020?
(change-ds-format "2019-12-29T00:00:00" )
;=> "12/29/2020 12:00:00 AM"
;; Why is this one 2020 ???
This looks ok:
(change-ds-format "2019-12-28T00:00:00" )
;=> "12/28/2019 12:00:00 AM"
and even this, same day from 2018 stays in the correct year:
(change-ds-format "2018-12-29T00:00:00" )
;=> "12/29/2018 12:00:00 AM"
I thought maybe it was a timezone offset issue but there is no way it should be shifting to the year 2020 I believe...
Just trying out java-time with clojure 1.8-RC5, I get the following:
user=> (require '[java-time :as t :reload-all true])
Reflection warning, java_time/single_field.clj:175:1 - call to static method of on java.time.MonthDay can't be resolved (argument types: java.time.Month, unknown).
Reflection warning, java_time/single_field.clj:183:1 - call to static method of on java.time.YearMonth can't be resolved (argument types: unknown, long).
Reflection warning, java_time/single_field.clj:183:1 - call to static method of on java.time.YearMonth can't be resolved (argument types: unknown, long).
Reflection warning, java_time/single_field.clj:183:1 - call to static method of on java.time.YearMonth can't be resolved (argument types: unknown, java.time.Month).
It seems the "unknown" types should be hinted to ints to please the clojure compiler. I note the relevant ctors have int in a comp; apparently, this is not sufficient for the clojure compiler to figure out that the ctors are returning ints.
This might be me abusing the API, in which case my apologies, but upgrading from 0.3.2 to 0.3.3 has lost various useful properties and keys I was relying on. For example the property :minute-of-day
no longer exists, and as-map
not longer returns :instant-seconds
. If there are more canonical ways to retrieve these I'd appreciate a pointer!
The docs for interval
(http://dm3.github.io/clojure.java-time/java-time.html#var-interval) do not mention that interval is only accessible if the project using java-time also pulls in java.threeten-extra, leading to a no-such-var
error when trying to use the library without this undocumented transitive dependency. It would be good if those dependencies were mentioned in the docs.
I want to parse a date for given string "Jan 1 2010"
. Since my locale is PL, (dt/local-date "MMM d yyyy" "Jan 1 2010")
doesn't work. What works is: (dt/local-date "MMM d yyyy" "sty 1 2010")
Is there any way to add locale for formatter?
This code works for me:
(dt/local-date (-> (java.time.format.DateTimeFormatterBuilder.)
(.appendPattern "MMM d yyyy")
(.toFormatter java.util.Locale/ENGLISH)) "Jan 1 2010")
Building 707f16daf19e04cf182cc532a2cce8db170ea178
using Leiningen, I get a test failure:
FAIL in (constructors) (java_time_test.clj:61)
enums
expected: (= (j/day-of-week 4) (j/day-of-week :thursday) (j/day-of-week (j/local-date clock)) (j/day-of-week "ee" "05"))
actual: (not (= #object[java.time.DayOfWeek 0x9d818b5 "THURSDAY"] #object[java.time.DayOfWeek 0x9d818b5 "THURSDAY"] #object[java.time.DayOfWeek 0x9d818b5 "THURSDAY"] #object[java.time.DayOfWeek 0x4f8e6101 "FRIDAY"]))
This is a locale issue. In a REPL with my system locale (English in Austria):
(ns jt-test (:require [java-time :as jt] [java-time.format :as jtf]))
=> nil
(jt/day-of-week (jtf/parse "ee" "05"))
=> #object[java.time.DayOfWeek 0x6ab351fe "FRIDAY"]
In a REPL with -Duser.country=US
set on the JVM:
(ns jt-test (:require [java-time :as jt] [java-time.format :as jtf]))
=> nil
(jt/day-of-week (jtf/parse "ee" "05"))
=> #object[java.time.DayOfWeek 0x67860a8c "THURSDAY"]
This is consistent with the expected first DoW being Sunday in the US, but Monday in (at least continental) Europe.
Hi @dm3, you've done a great job with this project. You've clearly put a lot of thought into it, and put the effort in to document it thoroughly. Thanks!
What do you think that most difficult challenges would be for someone to make a completely compatible CLJC version of this library?
Unfortunately it's in breach of the Clojure and Java trademarks to use them in your own software name. There is a valid risk of confusion too.
You might as well change it before Oracle makes you :)
e.g. from Clojure's license
I realize this is not the ideal place for questions, but searching for the past hour is not getting me an answer. Suppose I am provided with three strings ["10:00" "12:00" "17:00"]
. I need to be able to produce the right data structures to determine if one is within the interval of the other two; however, for the life of me I can't figure out how to do this. Doing local-time
on any of them works, but intervals require instants and instants can't be created that way. Help would be much appreciated.
Clojure beginner here. Tried installing as a lein dependency but I seem to be missing quite a few functions, for example:
zdttest.core=> (day-of-week now)
#object[java.time.DayOfWeek 0x3aad4eed "SUNDAY"]
zdttest.core=> (day-of-year now)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: day-of-year in this context, compiling:(/tmp/form-init3614178941667070356.clj:1:1)
zdttest.core=> (day-of-month now)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: day-of-month in this context, compiling:(/tmp/form-init3614178941667070356.clj:1:1)
This is my project.clj file:
(defproject zdttest "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"] [clojure.java-time "0.3.0"]]
:main ^:skip-aot zdttest.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
How can I fix this? Thank you,
I would assume there would be a "prettier" way to convert an instant to a ZonedDateTime
, because it looks clunky using Java interop (ofInstant
) like this:
(java.time.ZonedDateTime/ofInstant (java-time/instant "2021-05-16T22:00:00Z") (java-time/zone-id "Europe/Copenhagen"))
Is this the "best" way?
Can we add a new function, or at least an example for converting a Unix timestamp (epoch seconds) to a LocalDateTime
object? That seems like a very basic operation and I wasn't able to find a single example in the docs or test cases. Stackoverflow didn't even have examples either.
Use case, getting the modification time of a file, (me.raynes.fs/mod-time "example.txt")
returns epoch seconds.
Is it just an oversight on the imports?
Are there any other unexpectedly hidden functions?
(this came up when I pointed a beginner at clojure.java-time
and they were trying to parse string)
I have a nested data structure and I want to convert all the date time objects in it to ISO8601 timestamps during serialization. So, I need to find out what the timestamps are. I can't just try converting with instant
, because it'll try to convert strings, which I don't want.
inst?
is almost what I want, but Joda Time instances don't satisfy Inst
. This could be solved with something along the lines of the following:
(try
(Class/forName "org.joda.time.Instant")
(eval
'(extend-protocol Inst
org.joda.time.Instant
(inst-ms* [inst] (inst-ms* (jt/instant inst)))
org.joda.time.DateTime
(inst-ms* [inst] (inst-ms* (jt/instant inst)))))
(catch ClassNotFoundException cnfe))
(though this project already has a better when-joda
macro :))
Do you have a preferred solution?
java-time.repl
provides a show-path
function which provides a way to peek into the conversion graph. It's nice when one already knows the types used for the conversion, but doesn't help during the discovery phase. How do we see what's available?
One option would be to go through all of the:
java.time.*
typesconversion!
and generate a Graphviz visualization published together with the API docs.
sql-timestamp
now fails on trying to convert a long to an integer:
e.g. (time/sql-timestamp 1498582624546)
results in Value out of range for int: 1498582624546
In a previous version, 0.2.2, the expected behavior for longs was in place, but it was lost when I upgrade to 0.3.0. The actual regression may have been introduced in an earlier version, that is just the version I upgraded to as it is presently the latest release.
(jt/plus (jt/zoned-date-time) (jt/minutes 1))
=> #inst"2019-04-06T10:35:04.615-00:00"
(jt/plus (jt/minutes 1) (jt/zoned-date-time))
Execution error (ClassCastException) at java-time.amount/d-plus (amount.clj:12).
class java.time.ZonedDateTime cannot be cast to class java.time.Duration (java.time.ZonedDateTime and java.time.Duration are in module java.base of loader 'bootstrap')
Is there a way to get the value of a Duration in a unit, e.g. the number of seconds in a duration? Without resorting to interop, that is.
If you do not already have this capability, maybe something like:
(in duration :seconds)
since you've already committed to keyword representations of the various units as a part of the api in other calls?
Due to the var import, the vars in the java-time
namespace do not get autocompleted.
Issue registered with Cursive project at cursive-ide/cursive#1670.
I use (local-date-time "yyyy-MM-dd hh:mm:ss" "2018-02-01 12:11:05")
got error:
3. Unhandled clojure.lang.ExceptionInfo
Conversion failed
{:path
[[#object[java_time.graph.Types 0x4d2611bc "[java.lang.String java.lang.String]"]
#object[java_time.graph.Types 0xc16795a "[java.time.format.DateTimeFormatter java.lang.String]"]]
[#object[java_time.graph.Types 0x58001640 "[java.time.format.DateTimeFormatter java.lang.CharSequence]"]
#object[java_time.graph.Types 0x278849cc "[java.time.LocalDateTime]"]]],
:arguments ["yyyy-MM-dd hh:mm:ss" "2018-02-01 12:11:05"],
:to java.time.LocalDateTime}
core.clj: 4739 clojure.core/ex-info
core.clj: 4739 clojure.core/ex-info
local.clj: 52 java-time.local/local-date-time/fn
local.clj: 52 java-time.local/local-date-time
local.clj: 52 java-time.local/local-date-time
ea6dd32106c6cb9fe1eafbc1aa3a2b9e168e9e25-init.clj: 1 user/eval37656
ea6dd32106c6cb9fe1eafbc1aa3a2b9e168e9e25-init.clj: 1 user/eval37656
Compiler.java: 7062 clojure.lang.Compiler/eval
Compiler.java: 7025 clojure.lang.Compiler/eval
core.clj: 3206 clojure.core/eval
core.clj: 3202 clojure.core/eval
main.clj: 243 clojure.main/repl/read-eval-print/fn
main.clj: 243 clojure.main/repl/read-eval-print
main.clj: 261 clojure.main/repl/fn
main.clj: 261 clojure.main/repl
main.clj: 177 clojure.main/repl
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 652 clojure.core/apply
regrow.clj: 18 refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 1965 clojure.core/with-bindings*
core.clj: 1965 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 85 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 55 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 222 clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
interruptible_eval.clj: 190 clojure.tools.nrepl.middleware.interruptible-eval/run-next/fn
AFn.java: 22 clojure.lang.AFn/run
ThreadPoolExecutor.java: 1149 java.util.concurrent.ThreadPoolExecutor/runWorker
ThreadPoolExecutor.java: 624 java.util.concurrent.ThreadPoolExecutor$Worker/run
Thread.java: 748 java.lang.Thread/run
2. Caused by java.time.DateTimeException
Unable to obtain LocalDateTime from TemporalAccessor: {MilliOfSecond=0,
SecondOfMinute=5, NanoOfSecond=0, MicroOfSecond=0, HourOfAmPm=0, MinuteOfHour=11},ISO
resolved to 2018-02-01 of type java.time.format.Parsed
LocalDateTime.java: 461 java.time.LocalDateTime/from
local.clj: 138 java-time.local/eval35661/fn
AFn.java: 156 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 652 clojure.core/apply
defconversion.clj: 28 java-time.defconversion/combinations/iter/fn/fn/fn
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 652 clojure.core/apply
defconversion.clj: 21 java-time.defconversion/wrap-validation/fn
graph.clj: 310 java-time.graph/convert-via/fn/fn
PersistentUnrolledVector.java: 482 clojure.lang.PersistentUnrolledVector$Card2/reduce
core.clj: 6747 clojure.core/reduce
core.clj: 6730 clojure.core/reduce
graph.clj: 310 java-time.graph/convert-via/fn
local.clj: 52 java-time.local/local-date-time/fn
local.clj: 52 java-time.local/local-date-time
local.clj: 52 java-time.local/local-date-time
ea6dd32106c6cb9fe1eafbc1aa3a2b9e168e9e25-init.clj: 1 user/eval37656
ea6dd32106c6cb9fe1eafbc1aa3a2b9e168e9e25-init.clj: 1 user/eval37656
Compiler.java: 7062 clojure.lang.Compiler/eval
Compiler.java: 7025 clojure.lang.Compiler/eval
core.clj: 3206 clojure.core/eval
core.clj: 3202 clojure.core/eval
main.clj: 243 clojure.main/repl/read-eval-print/fn
main.clj: 243 clojure.main/repl/read-eval-print
main.clj: 261 clojure.main/repl/fn
main.clj: 261 clojure.main/repl
main.clj: 177 clojure.main/repl
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 652 clojure.core/apply
regrow.clj: 18 refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 1965 clojure.core/with-bindings*
core.clj: 1965 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 85 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 55 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 222 clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
interruptible_eval.clj: 190 clojure.tools.nrepl.middleware.interruptible-eval/run-next/fn
AFn.java: 22 clojure.lang.AFn/run
ThreadPoolExecutor.java: 1149 java.util.concurrent.ThreadPoolExecutor/runWorker
ThreadPoolExecutor.java: 624 java.util.concurrent.ThreadPoolExecutor$Worker/run
Thread.java: 748 java.lang.Thread/run
1. Caused by java.time.DateTimeException
Unable to obtain LocalTime from TemporalAccessor: {MilliOfSecond=0, SecondOfMinute=5,
NanoOfSecond=0, MicroOfSecond=0, HourOfAmPm=0, MinuteOfHour=11},ISO resolved to
2018-02-01 of type java.time.format.Parsed
LocalTime.java: 409 java.time.LocalTime/from
LocalDateTime.java: 457 java.time.LocalDateTime/from
local.clj: 138 java-time.local/eval35661/fn
AFn.java: 156 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 652 clojure.core/apply
defconversion.clj: 28 java-time.defconversion/combinations/iter/fn/fn/fn
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 652 clojure.core/apply
defconversion.clj: 21 java-time.defconversion/wrap-validation/fn
graph.clj: 310 java-time.graph/convert-via/fn/fn
PersistentUnrolledVector.java: 482 clojure.lang.PersistentUnrolledVector$Card2/reduce
core.clj: 6747 clojure.core/reduce
core.clj: 6730 clojure.core/reduce
graph.clj: 310 java-time.graph/convert-via/fn
local.clj: 52 java-time.local/local-date-time/fn
local.clj: 52 java-time.local/local-date-time
local.clj: 52 java-time.local/local-date-time
ea6dd32106c6cb9fe1eafbc1aa3a2b9e168e9e25-init.clj: 1 user/eval37656
ea6dd32106c6cb9fe1eafbc1aa3a2b9e168e9e25-init.clj: 1 user/eval37656
Compiler.java: 7062 clojure.lang.Compiler/eval
Compiler.java: 7025 clojure.lang.Compiler/eval
core.clj: 3206 clojure.core/eval
core.clj: 3202 clojure.core/eval
main.clj: 243 clojure.main/repl/read-eval-print/fn
main.clj: 243 clojure.main/repl/read-eval-print
main.clj: 261 clojure.main/repl/fn
main.clj: 261 clojure.main/repl
main.clj: 177 clojure.main/repl
RestFn.java: 137 clojure.lang.RestFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 652 clojure.core/apply
regrow.clj: 18 refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
RestFn.java: 1523 clojure.lang.RestFn/invoke
interruptible_eval.clj: 87 clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn
AFn.java: 152 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
core.clj: 657 clojure.core/apply
core.clj: 1965 clojure.core/with-bindings*
core.clj: 1965 clojure.core/with-bindings*
RestFn.java: 425 clojure.lang.RestFn/invoke
interruptible_eval.clj: 85 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 55 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj: 222 clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
interruptible_eval.clj: 190 clojure.tools.nrepl.middleware.interruptible-eval/run-next/fn
AFn.java: 22 clojure.lang.AFn/run
ThreadPoolExecutor.java: 1149 java.util.concurrent.ThreadPoolExecutor/runWorker
ThreadPoolExecutor.java: 624 java.util.concurrent.ThreadPoolExecutor$Worker/run
Thread.java: 748 java.lang.Thread/run
Thanks for an elegant wrapper.
I currently have to drop into interop to make a LocalDateRange
from org.threeten.extra
. Do you have any plans to bring it in? I note you already support Interval
from that library.
Can I help? I might need you to point me in the right direction to get started.
clojure.java-time
takes seconds to load:
Recent mBP, macOS 10.14, Clojure 1.8 or 1.10:
user=> (time (require 'java-time))
"Elapsed time: 1691.125038 msecs"
Slightly older mBP, macOS 10.14, Clojure 1.10:
user=> (time (use 'java-time))
"Elapsed time: 2776.996579 msecs"
Haven't tested on other OSes.
Hi there,
First of all, many thanks for your work on this - it is hugely appreciated :). Secondly, i think this library fits perfectly into the intended use-cases for the new Datafiable
protocol (Clojure 1.10). Any top-level object (e.g. LocalDateTime, ZonedDateTime etc) could/should be datafiable, and this would essentially remove the need for Java interop (for accessing individual fields) in the vast majority of cases. Would you be interested in a PR? It would boil down to a brand new data
namespace exposing a single public to-data
.
Again, thanks for your work... ;)
lein --version
Leiningen 2.9.3 on Java 1.8.0_212 OpenJDK 64-Bit Server VM
Using clojure 1.10.0 and java-time 0.3.2,
user=> (require '[java-time :as t])
nil
user=> (t/interval (t/instant) (t/instant))
Syntax error compiling at (target/8d19c48038470b12302e74f763fae3e2d7e82d87-init.clj:1:1).
No such var: t/interval
But I see interval
in the docs. Am I missing something obvious?
I also just noticed that tab completion seems to give me a non-deterministic count of the number of things in the namespace when I restart Edit: this part was me confusing myself when downgrading to java-time 0.3.0 to see if it contained lein repl
.interval
. Neither 0.3.0 nor 0.3.2 seem to contain the function.
Use js-joda as the javascript impl.
I get the below when trying to use java-time.
lein try clojure.java-time "0.3.2"
nREPL server started on port 41145 on host 127.0.0.1 - nrepl://127.0.0.1:41145
REPL-y 0.4.3, nREPL 0.6.0
Clojure 1.10.0
OpenJDK 64-Bit Server VM 1.8.0_212-8u212-b03-0ubuntu1.19.04.2-b03
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> (use 'java-time)
Syntax error (IllegalAccessError) compiling at (temporal.clj:324:1).
tried to access field clojure.lang.APersistentVector._hash from class clojure.lang.PersistentUnrolledVector$Card1
Environment:
Ubbuntu 19.04
javac 11.0.3
Leiningen 2.9.1 on Java 1.8.0_212 OpenJDK 64-Bit Server VM
The java.time.foo
objects that are returned by fns in this lib print as something like #object[java.time.Instant "0x6cc2abad" "2017-11-13T01:40:56.483Z"]
However these can't be used interactively as data because unlike java.util.Date's #inst "2017-11-13T01:41:43.571-00:00"
, the repl explodes when given the java.time.Instant
object. Since it complains about having no reader function for #object, I guess it's a matter of extending edn to recognize #objects.
Have you encountered this problem? Is this sth for this library to tackle, or for each end user to roll their own?
Hi there,
I am a beginner and wanted to use your example to get the next three days from today. That didn't work out as far as I can judge.
The repl tells me:
ArityException Wrong number of args (3) passed to: core/iterate clojure.lang.AFn.throwArity (AFn.java:429)
iterate indeed takes only two arguments and there are three. I would have created a pull-request but I am not able to solve this simple problem, sorry.
Three next days?
(take 3 (iterate plus now (days 1)))
=> (#object[java.time.LocalDate "2015-09-28"]
#object[java.time.LocalDate "2015-09-29"]
#object[java.time.LocalDate "2015-09-30"])
I see no reason why there should not be a conversion between these two types.
The following code serve the purpose:
(defn from-sql-date [^java.sql.Date date]
(.toLocalDate date))
(defn to-sql-date [^java.time.LocalDate date]
(java.sql.Date/valueOf date))
What do you think?
First of all, thanks for the library!
We (@estikado and I) are in the process of migrating an application from clj-time to clojure.java-time. Given we use Clojure spec, we were wondering if you folks would be interested in having an equivalent of clj-time's spec.
We can open a PR in the next days if that's ok for you.
Thanks!
From the README:
If you add an optional [org.threeten/threeten-extra "0.9"] dependency to the project, you will get an Interval, AmPm, DayOfMonth, DayOfYear, Quarter and YearQuarter data types as well as a couple more adjusters.
Per the threeten-extra project readme the most recent version of threeten-extra is 1.2. Are there any known incompatibilities between more recent versions of threeten-extra and clojure.java-time?
In my code I believe I've pulled in java-time correctly, using code such as:
(ns my.ns
(:require [java-time :as tm]))
and then called java-time fns including:
tm/instant
tm/zoned-date-time
tm/local-date
tm/format
tm/plus
tm/minus
tm/after?
However when I run the eastwood linter over my code, it gives an implicit-dependences
warning for each java-time fn I'm calling.
Am I requiring java-time incorrectly, is the java-time
ns not requiring all of the various other java-time-internal namespaces properly, or is this a false negative from eastwood? My code certainly seems to be functioning correctly, fwiw.
There doesn't seem to be a way to convert from Instant
to OffsetDateTime
or ZonedDateTime
, even though java.time.Instant
provides .atOffset
and .atZone
methods. This makes Instants the roach motel of clojure.java-time: easy to get in, but difficult to get out. I particularly find this issue because org.threeten.extra/Interval
uses Instants
as the endpoints and I'd like to convert those to ZonedDateTime
. Right now, I have to use Clojure's Java interop to call .atZone
directly.
Should we just use .until
or is there something built-in? In any case it would be worth documenting, finding out how many days / months / ... is between two days is common I'd believe.
Now I do
(.until (jt/local-date "2019-01-01") (jt/local-date "2019-02-13") (java.time.temporal.ChronoUnit/DAYS))
I have tried to do
(jt/as (jt/period (jt/local-date "2019-01-01") (jt/local-date "2019-02-13")) :days)
``` but it fails with "Period contains years or months"
Exception in thread "main" java.lang.ClassCastException: java_time.graph.Types cannot be cast to java.lang.Comparable
at clojure.lang.Util.compare(Util.java:153)
at clojure.lang.APersistentVector.compareTo(APersistentVector.java:439)
at java.util.concurrent.ConcurrentHashMap.compareComparables(ConcurrentHashMap.java:732)
at java.util.concurrent.ConcurrentHashMap$TreeBin.<init>(ConcurrentHashMap.java:2773)
at java.util.concurrent.ConcurrentHashMap.treeifyBin(ConcurrentHashMap.java:2630)
at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1063)
at java.util.concurrent.ConcurrentHashMap.putIfAbsent(ConcurrentHashMap.java:1535)
at java_time.potemkin.util$fast_memoize$fn__11705.invoke(util.clj:50)
at java_time.graph$has_source_type_QMARK_$contains_src_types_QMARK___12015$fn__12016.invoke(graph.clj:279)
at clojure.core$some.invokeStatic(core.clj:2701)
at java_time.graph$has_source_type_QMARK_$contains_src_types_QMARK___12015.invoke(graph.clj:279)
at clojure.core$some.invokeStatic(core.clj:2701)
at java_time.graph$has_source_type_QMARK_.invokeStatic(graph.clj:282)
at java_time.graph$fn__12042.invokeStatic(graph.clj:301)
at java_time.graph$fn__12042.invoke(graph.clj:300)
at java_time.potemkin.util$fast_memoize$fn__11705.invoke(util.clj:52)
at java_time.graph$conversion_fn.invokeStatic(graph.clj:316)
at java_time.zone$zoned_date_time.invokeStatic(zone.clj:152)
assignable?
might be the problematic line since there is a >
in line 72.
I must be missing something? Is there a reason that the Ordered protocol is not defined on the Instant type? Specifically, I want to call (time/before? (instant1) (instant2))
(str (t/month-day)) ;; => "--02-04"
I am writing a simple application for tracking my own time. I wanted to use an expression like (as the-month-day :month-of-year :day-of-month)
. However, this expression failed reporting that MonthDay
did not implement the As
protocol.
In a few moments, I will create a pull request with the changes that I made to both tests and source code to resolve this issue.
Running the following in JDK11 returns the local time correctly:
(def fmt (java-time/formatter "hh:mma"))
(java-time/local-time fmt "12:34AM")
But JDK14 throws an exception Text '12:34AM' could not be parsed at index 5
.
java.time.DateTimeFormatterBuilder
has two methods parseCaseSensitive
and parseCaseInsensitive
. Option map for formatter
could be extended to accept another key :case
with values :sensitive
or :insensitive
.
If that's acceptable, I can submit a pull request to implement this.
for performance and coding consistency I recommend representing predefined formatters in the java-time.format namespace using keywords rather than strings. I could put in a PR for this if there is agreement.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.