From 3306df151d8c95b50c869db5e9c1185ea9d1834c Mon Sep 17 00:00:00 2001 From: Cosmin Stejerean Date: Mon, 6 Feb 2012 14:25:48 +1100 Subject: [PATCH 1/3] fixed printing of java.util.Date instants during daylight savings --- src/clj/clojure/instant.clj | 26 ++++++++++++++++++-------- 1 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/clj/clojure/instant.clj b/src/clj/clojure/instant.clj index 247274e..bfd2f02 100644 --- a/src/clj/clojure/instant.clj +++ b/src/clj/clojure/instant.clj @@ -8,7 +8,8 @@ (ns clojure.instant (:import [java.util Calendar Date GregorianCalendar TimeZone] - [java.sql Timestamp])) + [java.sql Timestamp] + [java.text SimpleDateFormat])) ;;; ------------------------------------------------------------------------ @@ -163,26 +164,35 @@ with invalid arguments." (let [x (- (count s) 3)] (str (.substring s 0 x) ":" (.substring s x)))) -(defn- caldate->rfc3339 - "format java.util.Date or java.util.Calendar as RFC3339 timestamp." +(defn- cal->rfc3339 + "format java.util.Calendar as RFC3339 timestamp." + [c] + (fixup-offset (format "#inst \"%1$tFT%1$tT.%1$tL%1$tz\"" c))) + +(def date-formatter + (proxy [ThreadLocal] [] + (initialValue [] (SimpleDateFormat. "'#inst \"'yyyy-MM-dd'T'HH:mm:ss.SZ'\"'")))) + +(defn- date->rfc3339 + "format java.util.Date as RFC3339 timestamp." [d] - (fixup-offset (format "#inst \"%1$tFT%1$tT.%1$tL%1$tz\"" d))) + (fixup-offset (.format (.get date-formatter) d))) (defmethod print-method java.util.Date [^java.util.Date d, ^java.io.Writer w] - (.write w (caldate->rfc3339 d))) + (.write w (date->rfc3339 d))) (defmethod print-dup java.util.Date [^java.util.Date d, ^java.io.Writer w] - (.write w (caldate->rfc3339 d))) + (.write w (date->rfc3339 d))) (defmethod print-method java.util.Calendar [^java.util.Calendar c, ^java.io.Writer w] - (.write w (caldate->rfc3339 c))) + (.write w (cal->rfc3339 c))) (defmethod print-dup java.util.Calendar [^java.util.Calendar c, ^java.io.Writer w] - (.write w (caldate->rfc3339 c))) + (.write w (cal->rfc3339 c))) (defn- fixup-nanos ; 0123456789012345678901234567890123456 [^long nanos ^String s] ; #@2011-01-01T01:00:00.000000000+01:00 -- 1.7.5.4 From 18b476cc8bc56bb75beffeb7fb7dbb2d3fc1fe4e Mon Sep 17 00:00:00 2001 From: Cosmin Stejerean Date: Mon, 6 Feb 2012 23:07:58 -0500 Subject: [PATCH 2/3] added tests for round-tripping java.util.Date instants during DST --- test/clojure/test_clojure/reader.clj | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) diff --git a/test/clojure/test_clojure/reader.clj b/test/clojure/test_clojure/reader.clj index 3cfbf9f..5a3bce4 100644 --- a/test/clojure/test_clojure/reader.clj +++ b/test/clojure/test_clojure/reader.clj @@ -21,7 +21,8 @@ (:use [clojure.instant :only [read-instant-date read-instant-calendar read-instant-timestamp]]) - (:import clojure.lang.BigInt)) + (:import clojure.lang.BigInt + java.util.TimeZone)) ;; Symbols @@ -319,7 +320,6 @@ (deftest t-read) - (deftest Instants (testing "Instants are read as java.util.Date by default" (is (= java.util.Date (class #inst "2010-11-12T13:14:15.666")))) @@ -329,7 +329,16 @@ (is (= java.util.Date (class (read-string s))))) (testing "java.util.Date instants round-trips" (is (= (-> s read-string) - (-> s read-string pr-str read-string))))) + (-> s read-string pr-str read-string)))) + (testing "java.util.Date handling DST in time zones" + (let [dtz (TimeZone/getDefault)] + (try + ;; A timezone with DST in effect during 2010-11-12 + (TimeZone/setDefault (TimeZone/getTimeZone "Australia/Sydney")) + (is (= (-> s read-string) + (-> s read-string pr-str read-string))) + (finally (TimeZone/setDefault dtz)))) + (try))) (binding [*data-readers* {'inst read-instant-calendar}] (testing "read-instant-calendar produces java.util.Calendar" (is (instance? java.util.Calendar (read-string s)))) -- 1.7.5.4 From a3c89c15142809c90cc7cca51d74eebbad23edb2 Mon Sep 17 00:00:00 2001 From: Cosmin Stejerean Date: Tue, 7 Feb 2012 15:32:38 +1100 Subject: [PATCH 3/3] more comprehensive of round-tripping of java.util.Date by checking throughout the year --- test/clojure/test_clojure/reader.clj | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/test/clojure/test_clojure/reader.clj b/test/clojure/test_clojure/reader.clj index 5a3bce4..b9f6e2f 100644 --- a/test/clojure/test_clojure/reader.clj +++ b/test/clojure/test_clojure/reader.clj @@ -330,6 +330,11 @@ (testing "java.util.Date instants round-trips" (is (= (-> s read-string) (-> s read-string pr-str read-string)))) + (testing "java.util.Date instants round-trip throughout the year" + (doseq [month (range 1 13) day (range 1 29) hour (range 1 23)] + (let [s (format "#inst \"2010-%02d-%02dT%02d:14:15.666-06:00\"" month day hour)] + (is (= (-> s read-string) + (-> s read-string pr-str read-string)))))) (testing "java.util.Date handling DST in time zones" (let [dtz (TimeZone/getDefault)] (try -- 1.7.5.4