├── .gitignore ├── project.clj ├── README.md └── src └── java_time_dte └── install.clj /.gitignore: -------------------------------------------------------------------------------- 1 | /.nrepl-port 2 | /target 3 | /pom.xml 4 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject java-time-dte "2018-04-18" 2 | :description "Datomic type extensions for java.time classes" 3 | :url "https://github.com/magnars/java-time-dte" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :dependencies [] 7 | :profiles {:dev {:plugins [] 8 | :dependencies [[datomic-type-extensions "2018-04-18"] 9 | [org.clojure/clojure "1.8.0"]] 10 | :source-paths ["dev"]}}) 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Datomic type extensions for java.time 2 | 3 | This Clojure library installs custom Datomic types for 4 | [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html). 5 | This is not something Datomic supports, so use it with 6 | [datomic-type-extensions](https://github.com/magnars/datomic-type-extensions). 7 | 8 | ## Install 9 | 10 | Add `[java-time-dte "2018-04-18"]` to `:dependencies` in your `project.clj`. 11 | 12 | You will also need `datomic-type-extensions` and `datomic` on the class path. 13 | 14 | ## Usage 15 | 16 | This library lets you set `:dte/valueType` to these custom types: 17 | 18 | ```clj 19 | :java.time/duration 20 | :java.time/instant 21 | :java.time/local-date 22 | :java.time/local-date-time 23 | :java.time/local-time 24 | :java.time/month-day 25 | :java.time/offset-date-time 26 | :java.time/offset-time 27 | :java.time/period 28 | :java.time/year 29 | :java.time/year-month 30 | :java.time/zoned-date-time 31 | :java.time/zone-id 32 | :java.time/zone-offset 33 | :java.time/chrono-unit 34 | :java.time/chrono-field 35 | :java.time/month 36 | :java.time/day-of-week 37 | ``` 38 | 39 | Remember to require `java-time-dte.install` somewhere. 40 | 41 | See [datomic-type-extensions](https://github.com/magnars/datomic-type-extensions) for usage. 42 | 43 | ## License 44 | 45 | Copyright © Magnar Sveen, since 2018 46 | 47 | Distributed under the Eclipse Public License, the same as Clojure. 48 | -------------------------------------------------------------------------------- /src/java_time_dte/install.clj: -------------------------------------------------------------------------------- 1 | (ns java-time-dte.install 2 | (:require [datomic-type-extensions.types :as types]) 3 | (:import [java.time DayOfWeek Duration Instant LocalDate LocalDateTime LocalTime Month MonthDay OffsetDateTime OffsetTime Period Year YearMonth ZonedDateTime ZoneId ZoneOffset] 4 | [java.time.temporal ChronoField ChronoUnit])) 5 | 6 | (defmacro define-dte [id backing-type serialize-sig serialize-body deserialize-sig deserialize-body] 7 | `(do 8 | (defmethod types/get-backing-datomic-type ~id [_#] ~backing-type) 9 | (defmethod types/serialize ~id [_# ~@serialize-sig] ~serialize-body) 10 | (defmethod types/deserialize ~id [_# ~@deserialize-sig] ~deserialize-body))) 11 | 12 | (define-dte :java.time/duration :db.type/string 13 | [^Duration this] (.toString this) 14 | [^String s] (Duration/parse s)) 15 | 16 | (define-dte :java.time/instant :db.type/instant 17 | [^Instant this] (java.util.Date/from this) 18 | [^java.util.Date inst] (Instant/ofEpochMilli (.getTime inst))) 19 | 20 | (define-dte :java.time/local-date :db.type/string 21 | [^LocalDate this] (.toString this) 22 | [^String s] (LocalDate/parse s)) 23 | 24 | (define-dte :java.time/local-date-time :db.type/string 25 | [^LocalDateTime this] (.toString this) 26 | [^String s] (LocalDateTime/parse s)) 27 | 28 | (define-dte :java.time/local-time :db.type/string 29 | [^LocalTime this] (.toString this) 30 | [^String s] (LocalTime/parse s)) 31 | 32 | (define-dte :java.time/month-day :db.type/string 33 | [^MonthDay this] (.toString this) 34 | [^String s] (MonthDay/parse s)) 35 | 36 | (define-dte :java.time/offset-date-time :db.type/string 37 | [^OffsetDateTime this] (.toString this) 38 | [^String s] (OffsetDateTime/parse s)) 39 | 40 | (define-dte :java.time/offset-time :db.type/string 41 | [^OffsetTime this] (.toString this) 42 | [^String s] (OffsetTime/parse s)) 43 | 44 | (define-dte :java.time/period :db.type/string 45 | [^Period this] (.toString this) 46 | [^String s] (Period/parse s)) 47 | 48 | (define-dte :java.time/year :db.type/string 49 | [^Year this] (.toString this) 50 | [^String s] (Year/parse s)) 51 | 52 | (define-dte :java.time/year-month :db.type/string 53 | [^YearMonth this] (.toString this) 54 | [^String s] (YearMonth/parse s)) 55 | 56 | (define-dte :java.time/zoned-date-time :db.type/string 57 | [^ZonedDateTime this] (.toString this) 58 | [^String s] (ZonedDateTime/parse s)) 59 | 60 | (define-dte :java.time/zone-id :db.type/string 61 | [^ZoneId this] (.toString this) 62 | [^String s] (ZoneId/of s)) 63 | 64 | (define-dte :java.time/zone-offset :db.type/string 65 | [^ZoneOffset this] (.toString this) 66 | [^String s] (ZoneOffset/of s)) 67 | 68 | ;; enums 69 | 70 | (defmacro define-enum [id class enum-map] 71 | (let [lookup (gensym) 72 | reverse-lookup (gensym)] 73 | `(do 74 | (def ~lookup ~enum-map) 75 | 76 | (def ~reverse-lookup 77 | (into {} (map (juxt second first) ~lookup))) 78 | 79 | (define-dte ~id :db.type/keyword 80 | [this#] (or (~reverse-lookup this#) 81 | (throw (Exception. (str "Unknown constant " this# " for enum " ~(str class))))) 82 | [kw#] (or (~lookup kw#) 83 | (throw (Exception. (str kw# " is not a constant in enum " ~(str class))))))))) 84 | 85 | (define-enum :java.time/chrono-unit ChronoUnit 86 | {:centuries ChronoUnit/CENTURIES 87 | :days ChronoUnit/DAYS 88 | :decades ChronoUnit/DECADES 89 | :eras ChronoUnit/ERAS 90 | :forever ChronoUnit/FOREVER 91 | :half-days ChronoUnit/HALF_DAYS 92 | :hours ChronoUnit/HOURS 93 | :micros ChronoUnit/MICROS 94 | :millennia ChronoUnit/MILLENNIA 95 | :millis ChronoUnit/MILLIS 96 | :minutes ChronoUnit/MINUTES 97 | :months ChronoUnit/MONTHS 98 | :nanos ChronoUnit/NANOS 99 | :seconds ChronoUnit/SECONDS 100 | :weeks ChronoUnit/WEEKS 101 | :years ChronoUnit/YEARS}) 102 | 103 | (define-enum :java.time/chrono-field ChronoField 104 | {:aligned-day-of-week-in-month ChronoField/ALIGNED_DAY_OF_WEEK_IN_MONTH 105 | :aligned-day-of-week-in-year ChronoField/ALIGNED_DAY_OF_WEEK_IN_YEAR 106 | :aligned-week-of-month ChronoField/ALIGNED_WEEK_OF_MONTH 107 | :aligned-week-of-year ChronoField/ALIGNED_WEEK_OF_YEAR 108 | :ampm-of-day ChronoField/AMPM_OF_DAY 109 | :clock-hour-of-ampm ChronoField/CLOCK_HOUR_OF_AMPM 110 | :clock-hour-of-day ChronoField/CLOCK_HOUR_OF_DAY 111 | :day-of-month ChronoField/DAY_OF_MONTH 112 | :day-of-week ChronoField/DAY_OF_WEEK 113 | :day-of-year ChronoField/DAY_OF_YEAR 114 | :epoch-day ChronoField/EPOCH_DAY 115 | :era ChronoField/ERA 116 | :hour-of-ampm ChronoField/HOUR_OF_AMPM 117 | :hour-of-day ChronoField/HOUR_OF_DAY 118 | :instant-seconds ChronoField/INSTANT_SECONDS 119 | :micro-of-day ChronoField/MICRO_OF_DAY 120 | :micro-of-second ChronoField/MICRO_OF_SECOND 121 | :milli-of-day ChronoField/MILLI_OF_DAY 122 | :milli-of-second ChronoField/MILLI_OF_SECOND 123 | :minute-of-day ChronoField/MINUTE_OF_DAY 124 | :minute-of-hour ChronoField/MINUTE_OF_HOUR 125 | :month-of-year ChronoField/MONTH_OF_YEAR 126 | :nano-of-day ChronoField/NANO_OF_DAY 127 | :nano-of-second ChronoField/NANO_OF_SECOND 128 | :offset-seconds ChronoField/OFFSET_SECONDS 129 | :proleptic-month ChronoField/PROLEPTIC_MONTH 130 | :second-of-day ChronoField/SECOND_OF_DAY 131 | :second-of-minute ChronoField/SECOND_OF_MINUTE 132 | :year ChronoField/YEAR 133 | :year-of-era ChronoField/YEAR_OF_ERA}) 134 | 135 | (define-enum :java.time/month Month 136 | {:january Month/JANUARY 137 | :february Month/FEBRUARY 138 | :march Month/MARCH 139 | :april Month/APRIL 140 | :may Month/MAY 141 | :june Month/JUNE 142 | :july Month/JULY 143 | :august Month/AUGUST 144 | :september Month/SEPTEMBER 145 | :october Month/OCTOBER 146 | :november Month/NOVEMBER 147 | :december Month/DECEMBER}) 148 | 149 | (define-enum :java.time/day-of-week DayOfWeek 150 | {:monday DayOfWeek/MONDAY 151 | :tuesday DayOfWeek/TUESDAY 152 | :wednesday DayOfWeek/WEDNESDAY 153 | :thursday DayOfWeek/THURSDAY 154 | :friday DayOfWeek/FRIDAY 155 | :saturday DayOfWeek/SATURDAY 156 | :sunday DayOfWeek/SUNDAY}) 157 | --------------------------------------------------------------------------------