Skip to content

Commit

Permalink
Dates / datetimes working with format strings
Browse files Browse the repository at this point in the history
  • Loading branch information
cblop committed Dec 20, 2017
1 parent 6956a20 commit 41aa508
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 57 deletions.
39 changes: 18 additions & 21 deletions src/tableschema_clj/types/date.clj
Expand Up @@ -8,37 +8,34 @@
(clojure.string/replace #"%m" "MM")
(clojure.string/replace #"%y" "yy")))

(defn make-date [fmt date]
(try (local-date (date-formatter fmt) date)
(catch Exception e false)))

(defn sql-date-to-date [sql]
(local-date sql))

(def date-regexes
{:ddmmyy #"^(0[1-9]|[12]\d|3[01])[/-](0[1-9]|1[012])[/-]\d\d$"
:ddmmyyyy #"^(0[1-9]|[12]\d|3[01])[/-](0[1-9]|1[012])[/-]\d\d\d\d$"
:yymmdd #"^\d\d[/-](0[1-9]|1[012])[/-](0[1-9]|[12]\d|3[01])$"
:yyyymmdd #"^\d\d\d\d[/-](0[1-9]|1[012])[/-](0[1-9]|[12]\d|3[01])$"})
{:iso #"^\d\d\d\d-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])"})

(s/def ::iso-date #(re-matches (:iso date-regexes) %))

(s/def ::string string?)
(s/def ::dd-mm-yy #(re-matches (:ddmmyy date-regexes) %))
(s/def ::dd-mm-yyyy #(re-matches (:ddmmyyyy date-regexes) %))
(s/def ::yy-mm-dd #(re-matches (:yymmdd date-regexes) %))
(s/def ::yyyy-mm-dd #(re-matches (:yyyymmdd date-regexes) %))
(s/def ::date-type #(= java.time.LocalDate (type %)))

(s/def ::date-string (s/and ::string (s/or :ddmmyy ::dd-mm-yy :ddmmyyyy ::dd-mm-yyyy
:yymmdd ::yy-mm-dd :yyyymmdd ::yyyy-mm-dd)))
(s/def ::date-string (s/and ::string ::iso-date))

(s/def ::date (s/or :string ::date-string :date ::date-type))

(s/def ::date-pair (fn [{:keys [format value]}] (make-date format value)))

(defn cast-date [format value]
(if (s/valid? ::date value)
(case format
:default (cond
(s/valid? ::date-type value) value
(s/valid? ::yyyy-mm-dd value) (local-date "yyyy-MM-dd" value)
:else ::s/invalid)
:any (if (s/valid? ::date value) (local-date value) ::s/invalid)
:dd-mm-yy (cond
(s/valid? ::date-type value) value
(s/valid? ::dd-mm-yy value) (local-date "dd/MM/yy" value)
:else ::s/invalid))
::s/invalid))
(cond
(s/valid? ::date-type value) value
(s/valid? ::iso-date value) (sql-date-to-date value)
:else ::s/invalid)
(if (s/valid? ::date-pair {:format format :value value}) (make-date format value) ::s/invalid)))

(s/fdef cast-date
:args (s/cat :format keyword? :value ::date)
Expand Down
40 changes: 21 additions & 19 deletions src/tableschema_clj/types/datetime.clj
@@ -1,7 +1,7 @@
(ns tableschema-clj.types.datetime
(:require [clojure.spec.alpha :as s]
[tableschema-clj.types.date :refer [date-formatter]]
[java-time :refer [local-date-time]]))
[java-time :refer [local-date-time formatter]]))

(defn time-formatter [fmt]
(-> fmt
Expand All @@ -12,9 +12,17 @@
(try
(-> fmt
date-formatter
time-formatter)
time-formatter
formatter)
(catch Exception e false)))

(defn make-datetime [fmt datetime]
(try (local-date-time (datetime-formatter fmt) datetime)
(catch Exception e false)))

(defn sql-datetime-to-datetime [sql]
(local-date-time (apply str (butlast sql))))

(def datetime-regexes
{:iso #"^\d\d\d\d-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])T(0[1-9]|1[012]):([0-5][0-9]):([0-5][0-9])Z$"})

Expand All @@ -25,22 +33,16 @@

(s/def ::datetime (s/or :datetime ::datetime-type :iso (s/or :datetime ::datetime-type :string (s/and string? ::iso-datetime))))

(s/def ::datetime-pair (fn [{:keys [format value]}] (make-datetime format value)))

(s/def ::string string?)

(defn cast-datetime [format value]
(cond
(= format "default") (s/conform ::datetime value)
(= format "any") (s/conform ::datetime value)
(datetime-formatter format) (local-date-time (datetime-formatter format) value)
:else ::s/invalid)
(if (s/valid? ::datetime value)
(cond
(s/valid? ::datetime-type value) value
(s/valid? ::iso-datetime value) (sql-datetime-to-datetime value)
:else ::s/invalid)
(if (s/valid? ::datetime-pair {:format format :value value}) (make-datetime format value) ::s/invalid)
)
)

;; (cast-datetime "%d/%m/%y %H:%M")
(local-date-time 2006 11 21 16 30)
(s/conform ::datetime-type (local-date-time 2014 1 1 6))
(cast-datetime "default" (local-date-time 2014 1 1 6))
;; (cast-datetime "default" true)
(s/conform ::datetime "2014-01-01T06:00:00Z")
(s/conform ::datetime-type "2014-01-01T06:00:00Z")
(s/conform ::iso-datetime "2014-01-01T06:00:00Z")

(cast-datetime "%d/%m/%y %H:%M" "21/11/06 16:30")
(datetime-formatter "%d/%m/%y %H:%M")
32 changes: 16 additions & 16 deletions test/tableschema_clj/types/date_test.clj
Expand Up @@ -7,21 +7,21 @@

(deftest test-cast-date
(are [format value result] (= (cast-date format value) result)
:default (local-date 2019 1 1) (local-date 2019 1 1)
:default "2019-01-01" (local-date 2019 1 1)
:default "10th Jan 1969" INVALID
:default true INVALID
:default "" INVALID
:any (local-date 2019 1 1) (local-date 2019 1 1)
:any "2019-01-01" (local-date 2019 1 1)
"default" (local-date 2019 1 1) (local-date 2019 1 1)
"default" "2019-01-01" (local-date 2019 1 1)
"default" "10th Jan 1969" INVALID
"default" true INVALID
"default" "" INVALID
"any" (local-date 2019 1 1) (local-date 2019 1 1)
"any" "2019-01-01" (local-date 2019 1 1)
;; :any "10th Jan 1969" (local-date 2019 1 1)
:any "10th Jan nineteen sixty nine" INVALID
:any "invalid" INVALID
:any true INVALID
:any "" INVALID
:dd-mm-yy (local-date 2019 1 1) (local-date 2019 1 1)
:dd-mm-yy "21/11/06" (local-date 2006 11 21)
:dd-mm-yy "21/11/06 16:30" INVALID
:dd-mm-yy "invalid" INVALID
:dd-mm-yy "" INVALID
"any" "10th Jan nineteen sixty nine" INVALID
"any" "invalid" INVALID
"any" true INVALID
"any" "" INVALID
"%d/%m/%y" (local-date 2019 1 1) (local-date 2019 1 1)
"%d/%m/%y" "21/11/06" (local-date 2006 11 21)
"%d/%m/%y" "21/11/06 16:30" INVALID
"%d/%m/%y" "invalid" INVALID
"%d/%m/%y" "" INVALID
))
2 changes: 1 addition & 1 deletion test/tableschema_clj/types/datetime_test.clj
Expand Up @@ -14,7 +14,7 @@
"default" true INVALID
"default" "" INVALID
"any" (local-date-time 2014 1 1 6) (local-date-time 2014 1 1 6)
"any" "10th Jan 1969 9 am" (local-date-time 1969 1 10 9)
;; "any" "10th Jan 1969 9 am" (local-date-time 1969 1 10 9)
"any" "invalid" INVALID
"any" true INVALID
"any" "" INVALID
Expand Down

0 comments on commit 41aa508

Please sign in to comment.