Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita395408

Browse files
committed
Updated to Java commit b62df08 (2012.02.24): instant literals for Date and Timestamp should print in UTC
1 parentdbe67e3 commita395408

File tree

2 files changed

+142
-64
lines changed

2 files changed

+142
-64
lines changed

‎Clojure/Clojure.Source/clojure/instant.clj

Lines changed: 98 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
([test msg] `(when-not ~test (fail ~msg)))
2323
([test] `(verify ~test ~(str"failed:" (pr-str test)))))
2424

25-
(defmacro ^:privatedivisible?
25+
(defn-divisible?
2626
[num div]
27-
`(zero? (mod~num~div)))
27+
(zero? (mod num div)))
2828

29-
(defmacro ^:privateindivisible?
29+
(defn-indivisible?
3030
[num div]
31-
`(not (divisible?~num~div)))
31+
(not (divisible? num div)))
3232

3333

3434
;;; ------------------------------------------------------------------------
@@ -52,13 +52,13 @@ The function new-instant is called with the following arguments.
5252
5353
min max default
5454
--- ------------ -------
55-
years 09'999 N/A (s must provide years)
55+
years 0 9999 N/A (s must provide years)
5656
months 1 12 1
5757
days 1 31 1 (actual max days depends
5858
hours 0 23 0 on month and year)
5959
minutes 0 59 0
6060
seconds 0 60 0 (though 60 is only valid
61-
nanoseconds 0999'999'999 0 when minutes is 59)
61+
nanoseconds 0 999999999 0 when minutes is 59)
6262
offset-sign -1 1 0
6363
offset-hours 0 23 0
6464
offset-minutes 0 59 0
@@ -88,10 +88,9 @@ Grammar (of s):
8888
8989
Unlike RFC3339:
9090
91-
- we only consdier timestamp (was 'date-time')
92-
(removed: 'full-time', 'full-date')
91+
- we only parse the timestamp format
9392
- timestamp can elide trailing components
94-
- time-offset is optional
93+
- time-offset is optional (defaults to +00:00)
9594
9695
Though time-offset is syntactically optional, a missing time-offset
9796
will be treated as if the time-offset zero (+00:00) had been
@@ -158,52 +157,87 @@ with invalid arguments."
158157
;;; ------------------------------------------------------------------------
159158
;;; print integration
160159

161-
;;;(defn- fixup-offset
162-
;;; [^String s]
163-
;;; (let [x (- (count s) 3)]
164-
;;; (str (.Substring s 0 x) ":" (.Substring s x)))) ;;; .substring
165-
166-
(defn-caldate->rfc3339
167-
"format System.DateTime or System.DateTimeOffset as RFC3339 timestamp.";;; java.util.Date or java.util.Calendar
168-
[d]
169-
(format"#inst\"%1$tFT%1$tT.%1$tL%1$tz\"" d));;; took out fixup-offset wrapper call
160+
;;;(def ^:private thread-local-utc-date-format
161+
;;; ;; SimpleDateFormat is not thread-safe, so we use a ThreadLocal proxy for access.
162+
;;; ;; http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4228335
163+
;;; (proxy [ThreadLocal] []
164+
;;; (initialValue []
165+
;;; (doto (java.text.SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ss.SSS-00:00")
166+
;;; ;; RFC3339 says to use -00:00 when the timezone is unknown (+00:00 implies a known GMT)
167+
;;; (.setTimeZone (java.util.TimeZone/getTimeZone "GMT"))))))
168+
169+
(defn-print-datetime;;; print-date
170+
"Print a System.DateTime as RFC3339 timestamp, always in UTC.";;; java.util.Date
171+
[ ^System.DateTime d, ^System.IO.TextWriter w];;; ^java.util.Date ^java.io.Writer
172+
(let [utc-format"yyyy-MM-ddTHH:mm:ss.fff-00:00"];;; (.get thread-local-utc-date-format)
173+
(.Write w"#inst\"");;; .write
174+
(.Write w (.ToString d utc-format ));;; (.write w (.format utc-format d))
175+
(.Write w"\"")));;; .write
176+
177+
;;; DM Added
178+
(defn-print-datetimeoffset
179+
"Print a System.DateTimeOffset as RFC3339 timestamp, always in UTC."
180+
[ ^System.DateTimeOffset d, ^System.IO.TextWriter w]
181+
(let [utc-format"yyyy-MM-ddTHH:mm:ss.fffzzzz"]
182+
(.Write w"#inst\"")
183+
(.Write w (.ToString d utc-format ))
184+
(.Write w"\"")))
185+
;;;
170186

171187
(defmethodprint-methodSystem.DateTime;;; java.util.Date
172188
[^System.DateTime d, ^System.IO.TextWriter w];;; ^java.util.Date ^java.io.Writer
173-
(.Write w (caldate->rfc3339 d)));;;.write
189+
(print-datetime d w));;;print-date
174190

175191
(defmethodprint-dupSystem.DateTime;;; java.util.Date
176192
[^System.DateTime d, ^System.IO.TextWriter w];;; ^java.util.Date ^java.io.Writer
177-
(.Write w (caldate->rfc3339 d)));;; .write
193+
(print-datetime d w));;; print-date
194+
195+
;;;(defn- print-calendar
196+
;;; "Print a java.util.Calendar as RFC3339 timestamp, preserving timezone."
197+
;;; [^java.util.Calendar c, ^java.io.Writer w]
198+
;;; (let [calstr (format "%1$tFT%1$tT.%1$tL%1$tz" c)
199+
;;; offset-minutes (- (.length calstr) 2)]
200+
;;; ;; calstr is almost right, but is missing the colon in the offset
201+
;;; (.write w "#inst \"")
202+
;;; (.write w calstr 0 offset-minutes)
203+
;;; (.write w ":")
204+
;;; (.write w calstr offset-minutes 2)
205+
;;; (.write w "\"")))
178206

179207
(defmethodprint-methodSystem.DateTimeOffset;;; java.util.Calendar
180-
[^System.DateTimeOffsetc, ^System.IO.TextWriter w];;; ^java.util.Calendar ^java.io.Writer
181-
(.Write w (caldate->rfc3339 c)));;;.write
208+
[^System.DateTimeOffsetd, ^System.IO.TextWriter w];;; ^java.util.Calendar ^java.io.Writer
209+
(print-datetimeoffset d w));;;print-date
182210

183211
(defmethodprint-dupSystem.DateTimeOffset;;; java.util.Calendar
184-
[^System.DateTimeOffset c, ^System.IO.TextWriter w];;; ^java.util.Calendar ^java.io.Writer
185-
(.Write w (caldate->rfc3339 c)));;; .write
186-
187-
(defn-fixup-nanos; 0123456789012345678901234567890123456
188-
[^long nanos ^String s]; #@2011-01-01T01:00:00.000000000+01:00
189-
(str (.Substring s022);;; .substring
190-
(format"%09d" nanos)
191-
(.Substring s31)));;; .substring
192-
193-
;;;(defn- timestamp->rfc3339
194-
;;; [^java.sql.Timestamp ts]
195-
;;; (->> ts
196-
;;; (format "#inst \"%1$tFT%1$tT.%1$tN%1$tz\"") ; %1$tN prints 9 digits for frac.
197-
;;; fixup-offset ; second, but last 6 are always
198-
;;; (fixup-nanos (.getNanos ts)))) ; 0 though timestamp has getNanos
212+
[^System.DateTimeOffset d, ^System.IO.TextWriter w];;; ^java.util.Calendar ^java.io.Writer
213+
(print-datetimeoffset d w));;; print-date
214+
215+
;;;(def ^:private thread-local-utc-timestamp-format
216+
;;; ;; SimpleDateFormat is not thread-safe, so we use a ThreadLocal proxy for access.
217+
;;; ;; http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4228335
218+
;;; (proxy [ThreadLocal] []
219+
;;; (initialValue []
220+
;;; (doto (java.text.SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ss")
221+
;;; (.setTimeZone (java.util.TimeZone/getTimeZone "GMT"))))))
222+
223+
;;;(defn- print-timestamp
224+
;;; "Print a java.sql.Timestamp as RFC3339 timestamp, always in UTC."
225+
;;; [^java.sql.Timestamp ts, ^java.io.Writer w]
226+
;;; (let [utc-format (.get thread-local-utc-timestamp-format)]
227+
;;; (.write w "#inst \"")
228+
;;; (.write w (.format utc-format ts))
229+
;;; ;; add on nanos and offset
230+
;;; ;; RFC3339 says to use -00:00 when the timezone is unknown (+00:00 implies a known GMT)
231+
;;; (.write w (format ".%09d-00:00" (.getNanos ts)))
232+
;;; (.write w "\"")))
199233

200234
;;;(defmethod print-method java.sql.Timestamp
201-
;;; [^java.sql.Timestampt, ^java.io.Writer w]
202-
;;; (.write w (timestamp->rfc3339 t)))
235+
;;; [^java.sql.Timestampts, ^java.io.Writer w]
236+
;;; (print-timestamp ts w))
203237

204238
;;;(defmethod print-dup java.sql.Timestamp
205-
;;; [^java.sql.Timestampt, ^java.io.Writer w]
206-
;;; (.write w (timestamp->rfc3339 t)))
239+
;;; [^java.sql.Timestampts, ^java.io.Writer w]
240+
;;; (print-timestamp ts w))
207241

208242

209243
;;; ------------------------------------------------------------------------
@@ -229,11 +263,11 @@ but truncating the subsecond fraction to milliseconds."
229263
^DateTimeOffset
230264
[years months days hours minutes seconds nanoseconds
231265
offset-sign offset-hours offset-minutes]
232-
(DateTimeOffset. years months days hours minutes seconds
233-
(/ nanoseconds1000000)
234-
(if (neg? offset-sign)
235-
(TimeSpan. (- offset-hours) (- offset-minutes)0)
236-
(TimeSpan. offset-hours offset-minutes0))))
266+
(DateTimeOffset. years months days hours minutes seconds
267+
(/ nanoseconds1000000)
268+
(if (neg? offset-sign)
269+
(TimeSpan. (- offset-hours) (- offset-minutes)0)
270+
(TimeSpan. offset-hours offset-minutes0))))
237271
;;;
238272

239273

@@ -252,7 +286,7 @@ but truncating the subsecond fraction to milliseconds."
252286
milliseconds since the epoch, GMT."
253287
[years months days hours minutes seconds nanoseconds
254288
offset-sign offset-hours offset-minutes]
255-
(.LocalDateTime (construct-datetimeoffset years months days
289+
(.UtcDateTime (construct-datetimeoffset years months days
256290
hours minutes seconds nanoseconds
257291
offset-sign offset-hours offset-minutes)))
258292
;;;
@@ -270,23 +304,28 @@ milliseconds since the epoch, GMT."
270304
;;; (.setNanos nanoseconds)))
271305

272306
(defread-instant-datetime;;; read-instant-date
273-
"Bind this to *instant-reader* to read instants as System.DateTime.";;; java.util.Date.
274-
(partial parse-timestamp (validated construct-datetime)));;; construct-date
307+
"To read an instant as a System.DateTime, bind *data-readers* to a map with
308+
this var as the value for the 'inst key. The timezone offset will be used
309+
to convert into UTC."
310+
(partial parse-timestamp (validated construct-datetime)));;; construct-date
275311

276312
;;; DM: Added
277313
(defread-instant-datetimeoffset
278-
"Bind this to *instant-reader* to read instants as System.DateTimeOffset."
279-
(partial parse-timestamp (validated construct-datetimeoffset)))
314+
"To read an instant as a System.DateTimeOffset, bind *data-readers* to a map with
315+
this var as the value for the 'inst key. The timezone offset will be used
316+
to convert into UTC."
317+
(partial parse-timestamp (validated construct-datetimeoffset)))
280318
;;;
281319

282320
;;;(def read-instant-calendar
283-
;;; "Bind this to *instant-reader* toread instants as java.util.Calendar.
284-
;;;Calendar preservesthetimezone offset originally used inthedate
285-
;;;literal as written."
286-
;;;(partial parse-timestamp (validated construct-calendar)))
321+
;;;"To read an instant as a java.util.Calendar, bind *data-readers* toa map with
322+
;;;this var asthevalue for the 'inst key. Calendar preservesthetimezone
323+
;;;offset."
324+
;;; (partial parse-timestamp (validated construct-calendar)))
287325

288326
;;;(def read-instant-timestamp
289-
;;; "Bind this to *instant-reader* to read instants as
290-
;;;java.sql.Timestamp. Timestamp preserves fractional seconds with
291-
;;;nanosecond precision."
292-
;;; (partial parse-timestamp (validated construct-timestamp)))
327+
;;; "To read an instant as a java.sql.Timestamp, bind *data-readers* to a
328+
;;;map with this var as the value for the 'inst key. Timestamp preserves
329+
;;;fractional seconds with nanosecond precision. The timezone offset will
330+
;;;be used to convert into UTC."
331+
;;; (partial parse-timestamp (validated construct-timestamp)))

‎Clojure/Clojure.Tests/clojure/test_clojure/reader.clj

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
(:use [clojure.instant:only [read-instant-datetime;;; read-instant-date
2222
read-instant-datetimeoffset;;; read-instant-calendar
2323
]]);;; read-instant-timestamp
24-
(:import clojure.lang.BigInt))
24+
(:import clojure.lang.BigInt
25+
));;; java.util.TimeZone
2526

2627
;; Symbols
2728

@@ -329,7 +330,25 @@
329330
(is (= System.DateTime (class (read-string s)))));;; java.util.Date
330331
(testing"System.DateTime instants round-trips";;; java.util.Date
331332
(is (= (-> s read-string)
332-
(-> s read-string pr-str read-string)))))
333+
(-> s read-string pr-str read-string))))
334+
(testing"java.util.Date instants round-trip throughout the year"
335+
(doseq [month (range113) day (range129) hour (range123)]
336+
(let [s (format"#inst\"2010-%02d-%02dT%02d:14:15.666-06:00\"" month day hour)]
337+
(is (= (-> s read-string)
338+
(-> s read-string pr-str read-string))))))
339+
;;;(testing "java.util.Date handling DST in time zones" ;;; not sure how to do this
340+
;;; (let [dtz (TimeZone/getDefault)]
341+
;;; (try
342+
;;; ;; A timezone with DST in effect during 2010-11-12
343+
;;; (TimeZone/setDefault (TimeZone/getTimeZone "Australia/Sydney"))
344+
;;; (is (= (-> s read-string)
345+
;;; (-> s read-string pr-str read-string)))
346+
;;; (finally (TimeZone/setDefault dtz)))))
347+
(testing"java.util.Date should always print in UTC"
348+
(let [d (read-string s)
349+
pstr (print-str d)
350+
len (.Length pstr)];;;.length
351+
(is (= (subs pstr (- len7))"-00:00\"")))))
333352
(binding [*data-readers* {'inst read-instant-datetimeoffset}];;; read-instant-calendar
334353
(testing"read-instant-calendar produces System.DateTimeOffset";;; java.util.Calendar
335354
(is (instance? System.DateTimeOffset (read-string s))));;; java.util.Calendar
@@ -344,14 +363,34 @@
344363
(testing"System.DateTimeOffset preserves milliseconds";;; java.util.Calendar
345364
(is (=666 (-> s read-string
346365
(.Millisecond)))))));;; (.get java.util.Calendar/MILLISECOND)))))))
347-
;;;(let [s "#inst \"2010-11-12T13:14:15.123456789\""]
366+
;;;(let [s "#inst \"2010-11-12T13:14:15.123456789\""
367+
;;; s2 "#inst \"2010-11-12T13:14:15.123\""
368+
;;; s3 "#inst \"2010-11-12T13:14:15.123456789123\""]
348369
;;; (binding [*data-readers* {'inst read-instant-timestamp}]
349370
;;; (testing "read-instant-timestamp produces java.sql.Timestamp"
350371
;;; (is (= java.sql.Timestamp (class (read-string s)))))
351372
;;; (testing "java.sql.Timestamp preserves nanoseconds"
352373
;;; (is (= 123456789 (-> s read-string .getNanos)))
353-
;;; ;; bad ATM
354-
;;; #_(is (= 123456789 (-> s read-string pr-str read-string .getNanos)))))))
374+
;;; (is (= 123456789 (-> s read-string pr-str read-string .getNanos)))
375+
;;; ;; truncate at nanos for s3
376+
;;; (is (= 123456789 (-> s3 read-string pr-str read-string .getNanos))))
377+
;;; (testing "java.sql.Timestamp should compare nanos"
378+
;;; (is (= (read-string s) (read-string s3)))
379+
;;; (is (not= (read-string s) (read-string s2)))))
380+
;;; (binding [*data-readers* {'inst read-instant-date}]
381+
;;; (testing "read-instant-date should truncate at milliseconds"
382+
;;; (is (= (read-string s) (read-string s2)) (read-string s3)))))
383+
;;;(let [s "#inst \"2010-11-12T03:14:15.123+05:00\""
384+
;;; s2 "#inst \"2010-11-11T22:14:15.123Z\""]
385+
;;; (binding [*data-readers* {'inst read-instant-date}]
386+
;;; (testing "read-instant-date should convert to UTC"
387+
;;; (is (= (read-string s) (read-string s2)))))
388+
;;; (binding [*data-readers* {'inst read-instant-timestamp}]
389+
;;; (testing "read-instant-timestamp should convert to UTC"
390+
;;; (is (= (read-string s) (read-string s2)))))
391+
;;; (binding [*data-readers* {'inst read-instant-calendar}]
392+
;;; (testing "read-instant-calendar should preserve timezone"
393+
;;; (is (not= (read-string s) (read-string s2)))))))
355394
)
356395
;; UUID Literals
357396
;; #uuid "550e8400-e29b-41d4-a716-446655440000"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp