Share your thoughts in the 2024 State of Clojure Survey!

Welcome! Please see the About page for a little more info on how this works.

+2 votes
in Printing by
closed by

UPDATE:

https://clojure.org/news/2024/05/23/clojure-1-12-alpha12

Alpha12 reverted the change that caused this issue. This discussion is therefore obsolete.


I just noticed that Clojure 1.12 alpha10 has changed the way old #inst dates are created. As far as I can tell, Java is trying to adjust old dates before the Gregorian calendar was introduced.

In Clojure 1.11.3

user-> #inst "1582-02-24"
#inst "1582-02-24T00:00:00.000-00:00"

In Clojure 1.12-alpha10

user=> #inst "1582-02-24"
#inst "1582-03-06T00:00:00.000-00:00"

I found this when I ran some generative tests on an old project that tested dates. I'm changing my tests to look only at this millennium, which is fine for my application. I don't think Clojure should necessarily do anything to mitigate this change. I just thought it was worth a mention in case someone else bumps into it.

Updated to Clojure 1.12 alpha 11:

user=> (use 'clojure.instant)
nil
user=> (read-instant-date "1582-02-24")
#inst "1582-03-06T00:00:00.000-00:00"
user=> (read-instant-calendar "1582-02-24")
#inst "1582-02-24T00:00:00.000+00:00"
user=> (read-instant-timestamp "1582-02-24")
#inst "1582-03-06T00:00:00.000000000-00:00"
closed with the note: Reverted the original change, will consider changing both parser and formatter in tandem later
by
I'm learning a bit about the history of the transition from the Julian calendar to the Gregorian, and how proleptic Gregorian dates are handled in modern Java.  I'm starting to think that #inst should avoid proleptic dates altogether but I'm sure someone else has a more informed opinion.  Here are a couple of useful StackOverflow questions:

https://stackoverflow.com/questions/23975205/why-does-converting-java-dates-before-1582-to-localdate-with-instant-give-a-diff

https://stackoverflow.com/questions/23457470/calendar-to-date-conversion-for-dates-before-15-oct-1582-gregorian-to-julian-ca
by
I think the right thing to do is to reimplement most of instant.clj to use java.time.Instant as the basis.  That seems to fix things for me.

1 Answer

0 votes
by
edited by

Please disregard the below - I tested it using clojure.instant/read-instant-date directly and it seems that that's not what #inst ends up using in an plain REPL.


This has nothing to do with Java since changing the version of Clojure doesn't by itself change the version of Java that you're using.

A quick experiment shows that both versions parse the date in the same way - the call to (.getTime ...) returns the same -12238560000000.

So it seems that what's different is how the instances are printed. Commit 213c50e7 fixes CLJ-2803 by switching to a different printing method.

By using the old printing method manually with 1.12.0-alpha10, we can confirm the guess:

(let [fmt (java.text.SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ss.SSS-00:00")]
  (.setTimeZone fmt (java.util.TimeZone/getTimeZone "GMT"))
  (.format fmt d))
=> "1582-02-24T00:00:00.000-00:00"
by
How to quickly lose one's mind without bothering anyone:

    user=> (.getTime #inst "1582-02-24")
    -12237696000000
    user=> (let [d #inst "1582-02-24"] (.getTime d))
    -12237696000000
    user=> (def d #inst "1582-02-24")
    #'user/d
    user=> (.getTime d)
    -12238560000000  ;; What the hell?
...