Skip to content

Commit

Permalink
Fix coercion for xsd:dateTime, xsd:time in clj
Browse files Browse the repository at this point in the history
Fixes #580

The built-in java parsers will do the correct thing for subsecond values. We don't need to be doing any manual string-inspecting apart from determining whether an offset is present.
  • Loading branch information
mpoffald committed Sep 28, 2023
1 parent 824d0ad commit 12bacf5
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 35 deletions.
32 changes: 6 additions & 26 deletions src/fluree/db/datatype.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,9 @@
local timezone according to your device."
[s]
(when-let [matches (re-matches iso8601-time-re s)]
#?(:clj (let [time-parts (->> matches rest butlast)
offset (last matches)

[hours minutes seconds second-fraction]
(->> time-parts
(map #(or % "0"))
(map #(Integer/parseInt %)))

nanos (* second-fraction 1000000)]
(if offset
(OffsetTime/of hours minutes seconds nanos (ZoneOffset/of ^String offset))
(LocalTime/of hours minutes seconds nanos)))
#?(:clj (if-let [offset (peek matches)]
(OffsetTime/parse s)
(LocalTime/parse s))
:cljs (js/Date. (str "1970-01-01T" s)))))

(defn- parse-iso8601-datetime
Expand All @@ -157,20 +148,9 @@
[s]
(when-let [matches (re-matches iso8601-datetime-re s)]
#?(:clj
(let [datetime-parts (->> matches rest (take 7))
offset (last matches)
[years months days hours minutes seconds second-fraction]
(->> datetime-parts
(map #(or % "0"))
(map #(Integer/parseInt %)))

nanos (* second-fraction 1000000)]
(if offset
(OffsetDateTime/of years months days hours minutes seconds nanos
(ZoneOffset/of ^String offset))
(LocalDateTime/of ^int years ^int months ^int days ^int hours
^int minutes ^int seconds ^int nanos)))

(if-let [offset (peek matches)]
(OffsetDateTime/parse s)
(LocalDateTime/parse s))
:cljs
(js/Date. s))))

Expand Down
50 changes: 41 additions & 9 deletions test/fluree/db/datatype_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[fluree.db.constants :as const]
[fluree.db.datatype :refer [coerce]])
#?(:clj (:import (java.time LocalDate LocalTime OffsetDateTime OffsetTime
ZoneOffset))))
LocalDateTime ZoneOffset))))

(deftest coerce-test
(testing "strings"
Expand Down Expand Up @@ -55,16 +55,39 @@
(OffsetTime/of 9 30 10 0 (ZoneOffset/of "-06:00"))
:cljs
#inst "1970-01-01T09:30:10.000-06:00")
(coerce "09:30:10-06:00" const/$xsd:time)))
(coerce "09:30:10-06:00" const/$xsd:time)))
(is (= nil
(coerce "12:42:5" const/$xsd:time)))
(is (= nil
(coerce "12:42:5Z" const/$xsd:time)))
(testing "nanoseconds"
(is (= #?(:clj
(OffsetTime/of 11 14 32 833000000 (ZoneOffset/of "Z"))
:cljs
#inst "1970-01-01T11:14:32.833-00:00")
(coerce "11:14:32.833Z" const/$xsd:time)))
(is (= #?(:clj
(OffsetTime/of 11 14 32 830000000 (ZoneOffset/of "Z"))
:cljs
#inst "1970-01-01T11:14:32.83-00:00")
(coerce "11:14:32.83Z" const/$xsd:time)))
(is (= #?(:clj
(OffsetTime/of 11 14 32 833100000 (ZoneOffset/of "Z"))
;;only 3 digits of ms allowed in js
:cljs
nil)
(coerce "11:14:32.8331Z" const/$xsd:time)))
(is (= #?(:clj
(LocalTime/of 12 42 0 430000000)
:cljs
(js/Date. "1970-01-01T12:42:00.43"))
(coerce "12:42:00.43" const/$xsd:time))))
(is (= #?(:clj
(OffsetTime/of 11 14 32 833000000 (ZoneOffset/of "Z"))
(LocalTime/of 12 42 0 433100000)
;;only 3 digits of ms allowed in js
:cljs
#inst "1970-01-01T11:14:32.833-00:00")
(coerce "11:14:32.833Z" const/$xsd:time)))
nil)
(coerce "12:42:00.4331" const/$xsd:time)))
(is (= nil (coerce "foo" const/$xsd:time))))

(testing "datetime"
Expand All @@ -83,10 +106,19 @@
#inst "1980-10-05T11:23:00.000-00:00")
(coerce "1980-10-05T11:23:00Z" const/$xsd:dateTime))
"z")
(is (= #?(:clj (OffsetDateTime/of 2021 9 24 11 14 32 833000000 (ZoneOffset/of "Z")))
(coerce "2021-09-24T11:14:32.833Z" const/$xsd:dateTime))
"with nanoseconds")

(testing "nanoseconds"
(is (= #?(:clj (OffsetDateTime/of 2021 9 24 11 14 32 833000000 (ZoneOffset/of "Z")))
(coerce "2021-09-24T11:14:32.833Z" const/$xsd:dateTime)))
(is (= #?(:clj (OffsetDateTime/of 2021 9 24 11 14 32 833100000 (ZoneOffset/of "Z")))
(coerce "2021-09-24T11:14:32.8331Z" const/$xsd:dateTime)))
(is (= #?(:clj (OffsetDateTime/of 2021 9 24 11 14 32 830000000 (ZoneOffset/of "Z")))
(coerce "2021-09-24T11:14:32.83Z" const/$xsd:dateTime)))
(is (= #?(:clj (LocalDateTime/of 2021 9 24 11 14 32 833000000))
(coerce "2021-09-24T11:14:32.833" const/$xsd:dateTime)))
(is (= #?(:clj (LocalDateTime/of 2021 9 24 11 14 32 833100000))
(coerce "2021-09-24T11:14:32.8331" const/$xsd:dateTime)))
(is (= #?(:clj (LocalDateTime/of 2021 9 24 11 14 32 830000000))
(coerce "2021-09-24T11:14:32.83" const/$xsd:dateTime))))
(is (= nil (coerce "foo" const/$xsd:dateTime))))

(testing "decimal"
Expand Down

0 comments on commit 12bacf5

Please sign in to comment.