Skip to content

Commit

Permalink
Merge pull request #38 from yetanalytics/zero-second-dates
Browse files Browse the repository at this point in the history
Ensure zero-second times are valid
  • Loading branch information
kelvinqian00 authored Feb 20, 2024
2 parents ab9d947 + 9ee6e3a commit 628be5b
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
run: echo version=${GITHUB_REF#refs\/tags\/v} >> $GITHUB_OUTPUT

- name: Build and deploy to Clojars
uses: yetanalytics/actions/deploy-clojars@v0.0.4
uses: yetanalytics/action-deploy-clojars@v1
with:
artifact-id: 'flint'
resource-dirs: '[]'
Expand Down
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

## v0.3.0

- Add support for RDF List syntactic sugar.
- Add support for blank node vector syntactic sugar.
- Modify the AST tree for triples to support the new features and to remove redundant nodes in the tree.
- Add support for SPARQL collections syntactic sugar:
- Add support for RDF list syntax.
- Add support for blank node vector syntax.
- Modify the AST tree for triples to support the aforementioned features and to remove redundant nodes in the tree.
- Rework blank node validation to make the implementation simpler (this results in minor changes to the error output).
- Disallow syntax-quoting for symbols.
- Fix bug where timestamps with zeroed-out seconds have the seconds omitted.

## v0.2.1

Expand Down
53 changes: 45 additions & 8 deletions src/main/com/yetanalytics/flint/axiom/impl.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,27 @@
(defmacro extend-xsd-literal
"Macro that expands into a basic `extend-type` over the Literal protocol.
If `force-iri?` is true, then the resulting literal always has the XSD
datatype IRI appended; `strval-fn` overrides the default `.toString` call.
datatype IRI appended; `strval-fn` overrides the default call to `str`.
Without any kwargs, `(extend-xsd-literal t iri-suffix)` expands into:
```
(extend-type t p/Literal
(-valid-literal?
[_] true)
(-format-literal
([n] (p/-format-literal n {}))
([n opts] (fmt-impl/format-literal n opts)))
(-format-literal-strval
[n] (.toString n))
[n] (str n))
(-format-literal-lang-tag
[n] nil)
(-format-literal-url
([n] (p/-format-literal-url n {}))
([n opts] (fmt-impl/format-xsd-iri iri-suffix opts))))"
([n opts] (fmt-impl/format-xsd-iri iri-suffix opts))))
```"
[t iri-suffix & {:keys [force-iri?
strval-fn]}]
strval-fn]
:or {strval-fn str}}]
`(extend-type ~t
p/Literal
(~'-valid-literal? [~'_] true)
Expand All @@ -93,9 +96,7 @@
`(fmt-impl/format-literal ~'n (assoc ~'opts :force-iri? true))
`(fmt-impl/format-literal ~'n ~'opts))))
(~'-format-literal-strval [~'n]
~(if (some? strval-fn)
`(~strval-fn ~'n)
`(.toString ~'n)))
(~strval-fn ~'n))
(~'-format-literal-lang-tag [~'_] nil)
(~'-format-literal-url
([~'n] (p/-format-literal-url ~'n {}))
Expand Down Expand Up @@ -296,10 +297,41 @@
;; subclasses. The latter two have separate implementations since they throw
;; exceptions if `.toInstant` is directly called on them.

#?(:clj
(defn- local-ts->local-str
[^java.time.LocalDateTime local-ts]
(.format java.time.format.DateTimeFormatter/ISO_LOCAL_DATE_TIME
local-ts)))

#?(:clj
(defn- zoned-ts->offset-str
[^java.time.ZonedDateTime zoned-ts]
(.toString (.toOffsetDateTime zoned-ts))))
(.format java.time.format.DateTimeFormatter/ISO_OFFSET_DATE_TIME
(.toOffsetDateTime zoned-ts))))

#?(:clj
(defn- offset-ts->offset-str
[^java.time.OffsetDateTime offset-ts]
(.format java.time.format.DateTimeFormatter/ISO_OFFSET_DATE_TIME
offset-ts)))

#?(:clj
(defn- local-time->local-str
[^java.time.LocalTime local-time]
(.format java.time.format.DateTimeFormatter/ISO_LOCAL_TIME
local-time)))

#?(:clj
(defn- offset-time->offset-str
[^java.time.OffsetTime offset-time]
(.format java.time.format.DateTimeFormatter/ISO_OFFSET_TIME
offset-time)))

#?(:clj
(defn- local-date->local-str
[^java.time.LocalDate local-date]
(.format java.time.format.DateTimeFormatter/ISO_LOCAL_DATE
local-date)))

#?(:clj
(defn- date->inst-str
Expand Down Expand Up @@ -333,14 +365,19 @@
:strval-fn zoned-ts->offset-str
:force-iri? true)
(extend-xsd-literal java.time.OffsetDateTime "dateTime"
:strval-fn offset-ts->offset-str
:force-iri? true)
(extend-xsd-literal java.time.OffsetTime "time"
:strval-fn offset-time->offset-str
:force-iri? true)
(extend-xsd-literal java.time.LocalDateTime "dateTime"
:strval-fn local-ts->local-str
:force-iri? true)
(extend-xsd-literal java.time.LocalDate "date"
:strval-fn local-date->local-str
:force-iri? true)
(extend-xsd-literal java.time.LocalTime "time"
:strval-fn local-time->local-str
:force-iri? true)
;; java.util.Date classes
(extend-xsd-literal java.util.Date "dateTime"
Expand Down
50 changes: 43 additions & 7 deletions src/test/com/yetanalytics/flint/format/axiom_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
(:require [clojure.test :refer [deftest testing is]]
[com.yetanalytics.flint.axiom.iri :as iri]
[com.yetanalytics.flint.format :as f]
[com.yetanalytics.flint.format.axiom]))
[com.yetanalytics.flint.format.axiom])
#?(:clj (:import [java.time
Instant
LocalDate LocalTime LocalDateTime
OffsetTime OffsetDateTime
ZonedDateTime])))

(deftest axiom-format
(testing "Formatting terminal AST nodes"
Expand Down Expand Up @@ -56,18 +61,49 @@
ts-str-2 "\"1970-01-01T00:00:00Z\"^^xsd:dateTime"
ts-str-3 "\"1970-01-01\"^^xsd:date"
ts-str-4 "\"00:00:00Z\"^^xsd:time"
literal #inst "2022-01-20T16:22:19Z"
instant (java.time.Instant/parse "2022-01-20T16:22:19Z")
date (java.util.Date/from instant)
literal-1 #inst "2022-01-20T16:22:19Z"
literal-2 #inst "1970-01-01T00:00:00Z"
instant-1 (Instant/parse "2022-01-20T16:22:19Z")
instant-2 (Instant/parse "1970-01-01T00:00:00Z")
date (java.util.Date/from instant-1)
fmt-ts (fn [ts] (f/format-ast-node
{:iri-prefix-m {iri/xsd-iri-prefix "xsd"}}
[:ax/literal ts]))]
(is (= ts-str-1 (fmt-ts literal)))
(is (= ts-str-1 (fmt-ts instant)))
(is (= ts-str-1 (fmt-ts literal-1)))
(is (= ts-str-2 (fmt-ts literal-2)))
(is (= ts-str-1 (fmt-ts instant-1)))
(is (= ts-str-2 (fmt-ts instant-2)))
(is (= ts-str-1 (fmt-ts date)))
(is (= ts-str-2 (fmt-ts (java.sql.Timestamp. 0))))
(is (= ts-str-3 (fmt-ts (java.sql.Date. 0))))
(is (= ts-str-4 (fmt-ts (java.sql.Time. 0)))))
:cljs (is (string?
(f/format-ast-node {:iri-prefix-m {iri/xsd-iri-prefix "xsd"}}
[:ax/literal (js/Date.)]))))))
[:ax/literal (js/Date.)])))))
#?(:clj
(testing "DateTime formatting work on all java.time instances"
;; Note that here, zeroed-out seconds are preserved
(is (= "\"2022-01-20T16:22:00\"^^xsd:dateTime"
(f/format-ast-node
{:iri-prefix-m {iri/xsd-iri-prefix "xsd"}}
[:ax/literal (LocalDateTime/parse "2022-01-20T16:22:00")])))
(is (= "\"2022-01-20T16:22:00-05:00\"^^xsd:dateTime"
(f/format-ast-node
{:iri-prefix-m {iri/xsd-iri-prefix "xsd"}}
[:ax/literal (ZonedDateTime/parse "2022-01-20T16:22:00-05:00")])))
(is (= "\"2022-01-20T16:22:00-05:00\"^^xsd:dateTime"
(f/format-ast-node
{:iri-prefix-m {iri/xsd-iri-prefix "xsd"}}
[:ax/literal (OffsetDateTime/parse "2022-01-20T16:22:00-05:00")])))
(is (= "\"16:22:00\"^^xsd:time"
(f/format-ast-node
{:iri-prefix-m {iri/xsd-iri-prefix "xsd"}}
[:ax/literal (LocalTime/parse "16:22:00")])))
(is (= "\"16:22:00-05:00\"^^xsd:time"
(f/format-ast-node
{:iri-prefix-m {iri/xsd-iri-prefix "xsd"}}
[:ax/literal (OffsetTime/parse "16:22:00-05:00")])))
(is (= "\"2022-01-20\"^^xsd:date"
(f/format-ast-node
{:iri-prefix-m {iri/xsd-iri-prefix "xsd"}}
[:ax/literal (LocalDate/parse "2022-01-20")]))))))

0 comments on commit 628be5b

Please sign in to comment.