Create initial project structure with tests and reader

This commit is contained in:
Chris Hapgood
2024-06-06 15:38:31 -04:00
commit 92f61a3b69
8 changed files with 104 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.cpcache

7
.tool-versions Executable file
View File

@@ -0,0 +1,7 @@
# https://asdf-vm.com/
# Java:
java temurin-17.0.7+7
# Clojure:
clojure 1.11.1.1342

8
deps.edn Normal file
View File

@@ -0,0 +1,8 @@
{:deps {org.clojure/clojure {:mvn/version "1.11.2"}
org.threeten/threeten-extra {:mvn/version "1.8.0"}}
:paths ["src"]
:aliases {:test {:extra-paths ["test"]
:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
:git/sha "dfb30dd"
:git/tag "v0.5.1"}}
:exec-fn cognitect.test-runner.api/test}}}

6
src/challenge/core.clj Normal file
View File

@@ -0,0 +1,6 @@
(ns challenge.core
(:require [clojure.set :as set])
(:import (java.time LocalDate Period)
(org.threeten.extra LocalDateRange)))
(defn difference [& input])

34
src/challenge/readers.clj Normal file
View File

@@ -0,0 +1,34 @@
(ns challenge.readers
(:import (org.threeten.extra LocalDateRange)))
(defn local-date-range [s] (LocalDateRange/parse s))
(defn local-date-range-as-iso-interval
"Print the given LocalDateRange `ldr` as an ISO 8601-1:2019 interval in
<start>/<duration> format."
[ldr]
{:pre [(instance? LocalDateRange ldr)]}
(let [start (.getStart ldr)
period (.toPeriod ldr)]
;; NB: when the start date is the first day of the month and the duration is
;; one month, consider printing the interval as "YYYY-MM/P1M". This has the
;; advantage of naturally segregating month intervals from day intervals in
;; lexical sorts but has the disadvantage of not being parseable by the
;; LocalDateRange class nor by its sibling Interval class.
(str start "/" period)))
;; We elect to print a LocalDateRange using the ISO 8601-1:2019 <start>/<period>
;; representation. This is a compact and standardized representation that high-
;; lights our expected use case of specific periods (one day and one month).
;; The use of a LocalDate to represent the date-only start point is not well
;; publicized, probably because the relevant ISO standard (ISO 8601-2:2019) is
;; aggressively copyrighted and the use cases are few compared to other elements
;; of the standard.
(defmethod print-dup LocalDateRange
[o ^java.io.Writer w]
(doto w
(.write "#st/local-date-range \"")
(.write (local-date-range-as-iso-interval o))
(.write "\"")))
(defmethod print-method LocalDateRange [o ^java.io.Writer w] (print-dup o w))

1
src/data_readers.clj Normal file
View File

@@ -0,0 +1 @@
{st/local-date-range challenge.readers/local-date-range}

0
src/data_readers.edn Normal file
View File

47
test/challenge_test.clj Normal file
View File

@@ -0,0 +1,47 @@
(ns challenge-test
(:require [challenge.core :refer [difference]]
[challenge.readers]
[clojure.test :refer [deftest is testing]]))
(def week0 #st/local-date-range "2024-01-01/P7D")
(def week1 #st/local-date-range "2024-01-08/P7D")
(def week2 #st/local-date-range "2024-01-15/P7D")
(def week3 #st/local-date-range "2024-01-22/P7D")
(def extra #st/local-date-range "2024-01-29/P3D")
(def month0 #st/local-date-range "2024-01-01/P1M")
(deftest unary
(is (= #{week0}
(difference #{week0})))
(testing "compresses results"
(is (= #{month0}
(difference #{week0 week1 week2 week3 extra})))))
(deftest binary
(testing "equals"
(is (= #{}
(difference #{week0} #{week0})))
(is (= #{}
(difference #{week0 week1} #{week0 week1}))))
(testing "overlapped by"
(is (= #{#st/local-date-range "2024-01-01/P4D"}
(difference #{week0}
#{#st/local-date-range "2024-01-05/P10D"})))
(is (= #{#st/local-date-range "2024-01-01/P4D"}
(difference #{week0 week1}
#{#st/local-date-range "2024-01-05/P10D"}))))
(testing "met by"
(is (= #{week0}
(difference #{week0} #{week1}))))
(testing "contains"
(is (= #{week0 #st/local-date-range "2024-01-15/P17D"}
(difference #{month0} #{week1}))))
(testing "during"
(is (= #{}
(difference #{week1} #{month0})))))
(deftest variadic
(is (= #{week0 extra}
(difference #{month0}
#{week1}
#{week2 week3}))))