├── .github ├── FUNDING.yml └── workflows │ └── tests.yaml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── cljs.java-time.cljs.edn ├── deps.edn ├── dev-resources └── src-pom.xml ├── dev ├── build.clj ├── cljs.clj ├── externs.clj └── play.clj ├── src ├── cljs │ └── java_time │ │ ├── extend_eq_and_compare.cljs │ │ └── interop.cljc ├── cljsjs │ └── js-joda │ │ └── common │ │ └── js-joda-dup.ext.js ├── deps.cljs └── java │ ├── time.cljs │ └── time │ ├── format.cljs │ └── temporal.cljs ├── test └── cljs │ └── java_time │ └── extend_eq_and_compare_test.cljs └── web-target └── public └── .gitkeep /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: widdindustries 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/workflows/tests.yaml: -------------------------------------------------------------------------------- 1 | # https://practical.li/clojure/continuous-integration/github-actions/ 2 | name: Tests build 3 | on: [push, pull_request] 4 | jobs: 5 | clojure: 6 | runs-on: ubuntu-latest 7 | 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | 12 | - name: Prepare java 13 | uses: actions/setup-java@v2 14 | with: 15 | distribution: 'temurin' 16 | java-version: '17' 17 | 18 | - name: Install clojure tools 19 | uses: DeLaGuardo/setup-clojure@4.0 20 | with: 21 | cli: 1.10.1.693 # Clojure CLI based on tools.deps 22 | 23 | - name: Run Clj Unit tests 24 | run: make test-clj 25 | 26 | - name: Install Chrome 27 | uses: browser-actions/setup-chrome@latest 28 | 29 | - name: Run Cljs Unit tests 30 | run: make test-cljs-shadow -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cpcache 2 | node_modules 3 | .idea 4 | .shadow-cljs 5 | web-target/public/* 6 | package.json 7 | package-lock.json 8 | /target 9 | *.iml 10 | /classes 11 | /checkouts 12 | pom.xml.asc 13 | *.jar 14 | *.class 15 | /.lein-* 16 | /.nrepl-port 17 | .hgignore 18 | .hg/ 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Widd Industries Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test-clj: 2 | clojure -Atest -e deprecated 3 | test-cljs-shadow: 4 | clojure -Atest-cljs -X com.widdindustries.tiado-cljs2/tests-ci-shadow :compile-mode :release 5 | test-cljs-cljsjs: 6 | clojure -Atest-cljs -X non-non-shadow-tests/cljsjs :compile-mode :release 7 | test: 8 | make test-clj && make test-cljs-shadow && make test-cljs-cljsjs 9 | clean: 10 | clj -T:build clean 11 | install: 12 | make clean && clj -T:build jar && clj -T:build install \ 13 | && mkdir -p tmp && cd tmp 14 | deploy: 15 | clj -T:build deploy 16 | .PHONY: list 17 | list: 18 | @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Clojars Project](https://img.shields.io/clojars/v/com.widdindustries/cljs.java-time.svg)](https://clojars.org/com.widdindustries/cljs.java-time) 2 | 3 | [![Tests build](https://github.com/henryw374/time-literals/actions/workflows/tests.yaml/badge.svg)](https://github.com/henryw374/cljs.java-time/actions/workflows/tests.yaml) 4 | 5 | 6 | # cljs.java.time 7 | 8 | A Clojurescript library that provides the jsr-310 (java.time) api. 9 | 10 | Since v0.1.16 this requires Clojurescript version 1.10.741 or higher 11 | 12 | Underneath this lib is a pure JS implementation of java.time. This library just aims to make that 13 | library usable from Clojurescript: 14 | 15 | * it adds Clojurescript's equivalence, hash and comparison protocols to the java.time 16 | domain objects 17 | * it provides externs 18 | * the java.time packages are mirrored by Clojurescript namespaces. 19 | 20 | ## Related Libraries 21 | 22 | [cljc.java-time](https://github.com/henryw374/cljc.java-time) offers a one for one mapping of the classes and methods from 23 | java.time into a Clojure(Script) library 24 | 25 | Using that library is [tick](https://clojars.org/tick), an intuitive Clojure(Script) library for dealing with time, intended as a replacement for clj-time. 26 | 27 | [time-literals](https://github.com/henryw374/time-literals) is a Clojure(Script) library which provides tagged literals for objects from jsr-310 domain and depends on this library 28 | 29 | [my talk at Clojure/North 2019](https://www.youtube.com/watch?v=UFuL-ZDoB2U) provides some background 30 | 31 | ## Usage 32 | 33 | get it from [Clojars](https://clojars.org/cljs.java-time) 34 | 35 | If using cljsjs, add [js-joda](https://clojars.org/henryw374/js-joda) to your dependencies as well 36 | 37 | ``` 38 | (require '[java.time :refer [LocalDate]]) 39 | 40 | (.parse LocalDate "2020-01-01") 41 | ``` 42 | 43 | ### Shadow-Cljs 44 | 45 | At least one Shadow build (node-test) needs to be manually provided with externs, ie 46 | 47 | ``` 48 | :compiler-options {:externs ["cljsjs/js-joda/common/js-joda-dup.ext.js"]} 49 | ``` 50 | 51 | Shadow browser build and regular node build do not need any additional opts. 52 | 53 | ### Cross Platform (.cljc) Example 54 | 55 | ``` 56 | (ns foo 57 | (:require 58 | #?(:cljs [java.time :refer [LocalDate]]) 59 | [time-literals.read-write] 60 | [cljs.java-time.interop :as t.i]) 61 | #?(:clj (:import [java.time LocalDate]))) 62 | 63 | 64 | (. LocalDate parse "2020-12-01") 65 | ;=> #time/date"2020-12-01" 66 | 67 | (= 68 | (. LocalDate parse "2020-12-01") 69 | (. LocalDate parse "2020-12-01")) 70 | ; => true 71 | 72 | ; call a getter method 73 | (let [l (. LocalDate parse "2020-12-01")] 74 | (t.i/getter dayOfMonth l)) 75 | 76 | ``` 77 | 78 | ### Getter Methods 79 | Unfortunately, all java.time getter methods have had the 'get' part of their name removed in the underlying 80 | js lib. So instead of 'getNano' method, you have 'nano'. As a workaround, to write cross platform code that calls any getter methods on java.time objects, use the 81 | `cljs.java-time.interop/getter` macro 82 | 83 | 84 | 85 | ### NPM Dependency 86 | 87 | The npm library that provides the jsr-310 api is provided via a foreign-lib. 88 | Whilst this is handy if you don't already have an npm build step, if you do want to depend directly on the 89 | js-joda npm lib you can do so. For more info see the tick docs on [setup for use with ClojureScript](https://github.com/juxt/tick/blob/master/docs/cljs.adoc) 90 | 91 | ## License 92 | 93 | Copyright © 2019 Widd Industries 94 | 95 | Distributed under the [MIT License](/LICENSE) 96 | -------------------------------------------------------------------------------- /cljs.java-time.cljs.edn: -------------------------------------------------------------------------------- 1 | ^{:auto-testing true 2 | :open-url false 3 | :watch-dirs ["src" "test"]} 4 | {:main cljs.java-time.extend-eq-and-compare-test} -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src"] 2 | :deps {} 3 | :aliases {:build {:extra-deps {slipset/deps-deploy {:mvn/version "RELEASE"} 4 | io.github.clojure/tools.build {:git/tag "v0.8.2" :git/sha "ba1a2bf"}} 5 | :paths ["dev"] 6 | :ns-default build} 7 | :test {:extra-paths ["test"] 8 | :extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git" 9 | :sha "028a6d41ac9ac5d5c405dfc38e4da6b4cc1255d5"}} 10 | :main-opts ["-m" "cognitect.test-runner"]} 11 | :test-cljs {:extra-paths ["dev " "test" "web-target"] 12 | :extra-deps {com.widdindustries/tiado-cljs2 13 | { ;:local/root "../shadow-template" 14 | :git/url "https://github.com/henryw374/tiado-cljs2.git" 15 | :sha "fbd9f3b8df3523ccf11bbc685836ce7f96f18068" 16 | }}} 17 | }} 18 | -------------------------------------------------------------------------------- /dev-resources/src-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | Widd Industries Ltd 6 | http://widdindustries.com 7 | 8 | Provides the full java-time API to Clojure and Clojurescript 9 | https://github.com/henryw374/cljs.java-time 10 | 11 | 12 | http://opensource.org/licenses/MIT 13 | MIT 14 | 15 | 16 | 17 | jar 18 | 19 | https://github.com/henryw374/cljs.java-time 20 | scm:git:git@github.com:henryw374/cljs.java-time.git 21 | scm:git:git@github.com:henryw374/cljs.java-time.git 22 | 23 | 24 | 25 | clojars 26 | Clojars repository 27 | https://clojars.org/repo 28 | 29 | 30 | 31 | 32 | clojars 33 | https://repo.clojars.org/ 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /dev/build.clj: -------------------------------------------------------------------------------- 1 | (ns build 2 | (:require [clojure.tools.build.api :as b] 3 | [deps-deploy.deps-deploy :as dd] 4 | [clojure.java.shell :as sh] 5 | [clojure.string :as string])) 6 | (def lib 'com.widdindustries/cljs.java-time) 7 | (def version (some-> (sh/sh "git" "describe" "--tags" "--abbrev=0") 8 | :out 9 | (string/trim-newline))) 10 | 11 | (println "version " version) 12 | (def class-dir "target/classes") 13 | (def basis (b/create-basis {:project "deps.edn"})) 14 | (def jar-file (format "target/%s-%s.jar" (name lib) version)) 15 | 16 | (defn clean [_] 17 | (b/delete {:path "target"}) 18 | (sh/sh "rm" "-rf" "web-target/public/*") 19 | ) 20 | 21 | (defn jar [_] 22 | (b/write-pom {:src-pom "dev-resources/src-pom.xml" 23 | :class-dir class-dir 24 | :lib lib 25 | :version version 26 | :basis basis 27 | :src-dirs ["src"]}) 28 | (b/copy-dir {:src-dirs ["src"] 29 | :target-dir class-dir}) 30 | (b/jar {:class-dir class-dir 31 | :jar-file jar-file})) 32 | 33 | (defn install [_] 34 | (b/install {:basis basis 35 | :lib lib 36 | :version version 37 | :jar-file jar-file 38 | :class-dir class-dir}) 39 | (println (str "clj -Sdeps '{:deps {com.widdindustries/cljs.java-time {:mvn/version \"" version "\"}}}'")) 40 | ) 41 | 42 | (defn deploy [_] 43 | (dd/deploy {:installer :remote 44 | :artifact jar-file 45 | :pom-file (b/pom-path {:lib lib :class-dir class-dir})})) -------------------------------------------------------------------------------- /dev/cljs.clj: -------------------------------------------------------------------------------- 1 | (ns cljs 2 | (:require [com.widdindustries.tiadough-cljs2 :as util])) 3 | 4 | (defn test-watch [] 5 | (util/browser-test-build :watch {})) 6 | 7 | (comment 8 | 9 | ; start up live-compilation of tests 10 | (test-watch) 11 | ; run cljs tests, having opened browser at test page (see print output of above "for tests, open...") 12 | (util/run-tests) 13 | ; start a cljs repl session in the test build. :cljs/quit to exit 14 | (util/repl :browser-test-build) 15 | ; run tests in headless browser 16 | (util/compile-and-run-tests-headless* :release) 17 | 18 | (util/stop-server) 19 | 20 | ) -------------------------------------------------------------------------------- /dev/externs.clj: -------------------------------------------------------------------------------- 1 | (ns externs 2 | (:require [clojure.reflect :as r] 3 | [clojure.string :as string]) 4 | (:import [java.time Period 5 | Instant 6 | Duration 7 | LocalDate 8 | LocalTime 9 | ZonedDateTime 10 | OffsetDateTime 11 | OffsetTime 12 | LocalDateTime 13 | Year 14 | YearMonth 15 | ZoneId 16 | DayOfWeek 17 | Month 18 | Clock 19 | ZoneOffset] 20 | [java.time.format DateTimeFormatter 21 | ResolverStyle] 22 | [java.time.temporal ChronoUnit 23 | ChronoField 24 | TemporalAdjusters 25 | Temporal 26 | TemporalAmount])) 27 | 28 | (def classes [Period 29 | Instant 30 | Duration 31 | LocalDate 32 | LocalTime 33 | ZonedDateTime 34 | OffsetDateTime 35 | OffsetTime 36 | LocalDateTime 37 | Year 38 | YearMonth 39 | ZoneId 40 | DayOfWeek 41 | Month 42 | Clock 43 | ZoneOffset 44 | ChronoUnit 45 | ChronoField 46 | TemporalAdjusters 47 | Temporal 48 | TemporalAmount 49 | DateTimeFormatter 50 | ResolverStyle]) 51 | 52 | (defn static-method-names [class] 53 | ;(println "**** " class) 54 | (let [{:keys [bases members]} (r/reflect class)] 55 | (concat 56 | (->> bases 57 | (map #(-> % resolve)) 58 | (filter #(.startsWith (.getName (.getPackage %)) "java.time")) 59 | (map 60 | #(do ;(println "+++++++++ " %) 61 | (static-method-names %))) 62 | flatten) 63 | (->> members 64 | (filter (complement #((-> % :flags) :private))) 65 | (filter #((-> % :flags) :static)) 66 | (filter #(:return-type %)) 67 | (map :name) 68 | )))) 69 | 70 | (defn add-js-joda-getters [members] 71 | (concat members 72 | (->> members 73 | (keep (fn [member] 74 | (when-let [[_ cap remainder] (re-find #"get([A-Z])(.*)" member)] 75 | (str (string/lower-case cap) remainder))))))) 76 | 77 | (defn print-static-method-externs! [[class methods]] 78 | (let [joda-name (-> class (.getSimpleName))] 79 | (println (str "JSJoda." joda-name)) 80 | (doseq [method methods] 81 | (println (str "JSJoda." joda-name "." method))))) 82 | 83 | (comment 84 | 85 | (def statics 86 | (->> classes 87 | ;(take 1) 88 | (map (juxt identity 89 | static-method-names)) 90 | 91 | #_(map (fn [class] 92 | [(.getName class) 93 | ((comp add-js-joda-getters 94 | #(map str %) 95 | set 96 | static-method-names) 97 | class)])) 98 | )) 99 | 100 | (doseq [s statics] 101 | (print-static-method-externs! s)) 102 | 103 | ) 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /dev/play.clj: -------------------------------------------------------------------------------- 1 | (ns play 2 | (:import [java.time LocalDate 3 | LocalDateTime 4 | ZonedDateTime 5 | OffsetTime 6 | Instant 7 | OffsetDateTime 8 | LocalTime 9 | Year 10 | YearMonth])) 11 | 12 | 13 | (require '[clojure.reflect :as r]) 14 | 15 | 16 | 17 | ;(require '[clojure.pprint :as p]) 18 | ;(p/pprint (set (names java.time.Period))) 19 | ;(p/pprint (set (names java.time.chrono.ChronoPeriod))) 20 | 21 | (def nowable 22 | [LocalDate 23 | LocalDateTime 24 | ZonedDateTime 25 | OffsetTime 26 | Instant 27 | OffsetDateTime 28 | LocalTime 29 | Year 30 | YearMonth 31 | ]) 32 | 33 | (doseq [c nowable] 34 | (let [inst-1 (. LocalDate now)]) 35 | 36 | ) -------------------------------------------------------------------------------- /src/cljs/java_time/extend_eq_and_compare.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.java-time.extend-eq-and-compare) 2 | 3 | ;; 4 | ;; Empty file, kept for backward compatibility reasons. 5 | ;; All equality and hash protocol implementations moved to java/time.cljs 6 | ;; 7 | -------------------------------------------------------------------------------- /src/cljs/java_time/interop.cljc: -------------------------------------------------------------------------------- 1 | (ns cljs.java-time.interop 2 | "unfortunately the java.time getter methods have been renamed in js-joda to remove the 'get' part of the name, 3 | so in order to write cross platform code that calls a getter, the 'getter' macro can be used" 4 | #?(:clj 5 | (:require [net.cgrand.macrovich :as macros]) 6 | :cljs 7 | (:require-macros 8 | [net.cgrand.macrovich :as macros] 9 | [cljs.java-time.interop :refer [getter]]))) 10 | 11 | (macros/deftime 12 | 13 | (defmacro getter 14 | "To call .getZone method on object 'zdt' use as follows: 15 | (cljs.java-time.interop/getter zone zdt)" 16 | [p t & args] 17 | (macros/case 18 | :clj (let [[start & remainder] (str p)] 19 | (apply list (symbol (str ".get" (clojure.string/upper-case start) (apply str remainder))) t args)) 20 | :cljs (apply list (symbol (str "." p)) t args)))) 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/deps.cljs: -------------------------------------------------------------------------------- 1 | {:npm-deps {"@js-joda/core" "3.2.0"} 2 | :externs ["cljsjs/js-joda/common/js-joda-dup.ext.js"]} -------------------------------------------------------------------------------- /src/java/time.cljs: -------------------------------------------------------------------------------- 1 | (ns java.time 2 | (:require 3 | [goog.object] 4 | ["@js-joda/core" :as js-joda])) 5 | 6 | (def Period (goog.object/get js-joda "Period")) 7 | (def Instant (goog.object/get js-joda "Instant")) 8 | (def Duration (goog.object/get js-joda "Duration")) 9 | (def LocalDate (goog.object/get js-joda "LocalDate")) 10 | (def LocalTime (goog.object/get js-joda "LocalTime")) 11 | (def ZonedDateTime (goog.object/get js-joda "ZonedDateTime")) 12 | (def LocalDateTime (goog.object/get js-joda "LocalDateTime")) 13 | (def MonthDay (goog.object/get js-joda "MonthDay")) 14 | (def Year (goog.object/get js-joda "Year")) 15 | (def YearMonth (goog.object/get js-joda "YearMonth")) 16 | (def ZoneId (goog.object/get js-joda "ZoneId")) 17 | (def DayOfWeek (goog.object/get js-joda "DayOfWeek")) 18 | (def Month (goog.object/get js-joda "Month")) 19 | (def Clock (goog.object/get js-joda "Clock")) 20 | (def ZoneOffset (goog.object/get js-joda "ZoneOffset")) 21 | (def OffsetDateTime (goog.object/get js-joda "OffsetDateTime")) 22 | (def OffsetTime (goog.object/get js-joda "OffsetTime")) 23 | 24 | (extend-protocol IComparable 25 | Period (-compare [x y] (.compareTo ^js/Object x y)) 26 | LocalDate (-compare [x y] (.compareTo ^js/Object x y)) 27 | LocalDateTime (-compare [x y] (.compareTo ^js/Object x y)) 28 | ZonedDateTime (-compare [x y] (.compareTo ^js/Object x y)) 29 | OffsetTime (-compare [x y] (.compareTo ^js/Object x y)) 30 | Instant (-compare [x y] (.compareTo ^js/Object x y)) 31 | OffsetDateTime (-compare [x y] (.compareTo ^js/Object x y)) 32 | LocalTime (-compare [x y] (.compareTo ^js/Object x y)) 33 | Duration (-compare [x y] (.compareTo ^js/Object x y)) 34 | Year (-compare [x y] (.compareTo ^js/Object x y)) 35 | YearMonth (-compare [x y] (.compareTo ^js/Object x y)) 36 | ZoneId (-compare [x y] (.compareTo ^js/Object x y)) 37 | DayOfWeek (-compare [x y] (.compareTo ^js/Object x y)) 38 | Month (-compare [x y] (.compareTo ^js/Object x y)) 39 | MonthDay (-compare [x y] (.compareTo ^js/Object x y))) 40 | 41 | 42 | (extend-protocol IEquiv 43 | Period (-equiv [x y] (.equals ^js/Object x y)) 44 | LocalDate (-equiv [x y] (.equals ^js/Object x y)) 45 | LocalDateTime (-equiv [x y] (.equals ^js/Object x y)) 46 | ZonedDateTime (-equiv [x y] (.equals ^js/Object x y)) 47 | OffsetTime (-equiv [x y] (.equals ^js/Object x y)) 48 | Instant (-equiv [x y] (.equals ^js/Object x y)) 49 | OffsetDateTime (-equiv [x y] (.equals ^js/Object x y)) 50 | LocalTime (-equiv [x y] (.equals ^js/Object x y)) 51 | Duration (-equiv [x y] (.equals ^js/Object x y)) 52 | Year (-equiv [x y] (.equals ^js/Object x y)) 53 | YearMonth (-equiv [x y] (.equals ^js/Object x y)) 54 | ZoneId (-equiv [x y] (.equals ^js/Object x y)) 55 | DayOfWeek (-equiv [x y] (.equals ^js/Object x y)) 56 | Month (-equiv [x y] (.equals ^js/Object x y)) 57 | MonthDay (-equiv [x y] (.equals ^js/Object x y))) 58 | 59 | 60 | (extend-protocol IHash 61 | Period (-hash [x] (.hashCode ^js/Object x)) 62 | LocalDate (-hash [x] (.hashCode ^js/Object x)) 63 | LocalDateTime (-hash [x] (.hashCode ^js/Object x)) 64 | ZonedDateTime (-hash [x] (.hashCode ^js/Object x)) 65 | OffsetTime (-hash [x] (.hashCode ^js/Object x)) 66 | Instant (-hash [x] (.hashCode ^js/Object x)) 67 | OffsetDateTime (-hash [x] (.hashCode ^js/Object x)) 68 | LocalTime (-hash [x] (.hashCode ^js/Object x)) 69 | ; todo - do a PR with the hashCode methods to js-joda 70 | ; note - impls copied from java.time 71 | MonthDay (-hash [x] (+ (.dayOfMonth ^js/Object x) 72 | (bit-shift-left 73 | (let [y (.month ^js/Object x)] 74 | (.value ^js/Object y)) 6))) 75 | Duration (-hash [^js/Object x] 76 | (+ (* (.nano ^js/Object x) 51) 77 | (int 78 | (bit-xor 79 | (.seconds ^js/Object x) 80 | (unsigned-bit-shift-right (.seconds ^js/Object x) 32))))) 81 | Year (-hash [x] (.value ^js/Object x)) 82 | YearMonth (-hash [x] (bit-xor 83 | (.year ^js/Object x) 84 | (bit-shift-left (.monthValue ^js/Object x) 27))) 85 | ZoneId (-hash [x] (.hashCode ^js/Object x)) 86 | DayOfWeek (-hash [^js/Object x] (.value ^js/Object x)) 87 | Month (-hash [x] (.value ^js/Object x))) 88 | 89 | -------------------------------------------------------------------------------- /src/java/time/format.cljs: -------------------------------------------------------------------------------- 1 | (ns java.time.format 2 | (:require [goog.object] 3 | ["@js-joda/core" :as js-joda])) 4 | 5 | (def DateTimeFormatter (goog.object/get js-joda "DateTimeFormatter")) 6 | (def DateTimeFormatterBuilder (goog.object/get js-joda "DateTimeFormatterBuilder")) 7 | (def DecimalStyle (goog.object/get js-joda "DecimalStyle")) 8 | (def ResolverStyle (goog.object/get js-joda "ResolverStyle")) 9 | (def SignStyle (goog.object/get js-joda "SignStyle")) 10 | (def TextStyle (goog.object/get js-joda "TextStyle")) 11 | -------------------------------------------------------------------------------- /src/java/time/temporal.cljs: -------------------------------------------------------------------------------- 1 | (ns java.time.temporal 2 | (:require [goog.object] 3 | ["@js-joda/core" :as js-joda])) 4 | 5 | (def TemporalAdjusters (goog.object/get js-joda "TemporalAdjusters")) 6 | (def Temporal (goog.object/get js-joda "Temporal")) 7 | (def TemporalAmount (goog.object/get js-joda "TemporalAmount")) 8 | (def ChronoUnit (goog.object/get js-joda "ChronoUnit")) 9 | (def ChronoField (goog.object/get js-joda "ChronoField")) 10 | (def IsoFields (goog.object/get js-joda "IsoFields")) 11 | (def TemporalAccessor (goog.object/get js-joda "TemporalAccessor")) 12 | (def TemporalAdjuster (goog.object/get js-joda "TemporalAdjuster")) 13 | (def TemporalQuery (goog.object/get js-joda "TemporalQuery")) 14 | (def TemporalQueries (goog.object/get js-joda "TemporalQueries")) 15 | (def TemporalUnit (goog.object/get js-joda "TemporalUnit")) 16 | (def ValueRange (goog.object/get js-joda "ValueRange")) 17 | (def TemporalField (goog.object/get js-joda "TemporalField")) 18 | -------------------------------------------------------------------------------- /test/cljs/java_time/extend_eq_and_compare_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.java-time.extend-eq-and-compare-test 2 | (:require [clojure.test :refer [deftest is are]] 3 | [java.time :refer [LocalDate 4 | LocalDateTime 5 | ZonedDateTime 6 | OffsetTime 7 | Instant 8 | OffsetDateTime 9 | LocalTime 10 | Year 11 | YearMonth 12 | Month 13 | Duration 14 | Period 15 | ZoneId 16 | DayOfWeek 17 | MonthDay]] 18 | [java.time.format :refer [DateTimeFormatter 19 | DateTimeFormatterBuilder 20 | ResolverStyle]] 21 | [java.time.temporal :refer [ChronoField 22 | IsoFields]])) 23 | 24 | (def nowable 25 | [LocalDate 26 | LocalDateTime 27 | ZonedDateTime 28 | OffsetTime 29 | Instant 30 | OffsetDateTime 31 | LocalTime 32 | Year 33 | YearMonth 34 | MonthDay]) 35 | 36 | (def others [(. Month -MAY) 37 | (. Duration parse "PT1M") 38 | (. Period parse "P1D") 39 | (. ZoneId systemDefault) 40 | (. DayOfWeek -MONDAY)]) 41 | 42 | (defn assert-fns [x] 43 | (println x) 44 | (is (= x x)) 45 | (is (hash x)) 46 | (is (>= x x)) 47 | (is (<= x x))) 48 | 49 | (deftest test-extensions 50 | (doseq [c nowable] 51 | (assert-fns (. c now))) 52 | (doseq [o others] 53 | (assert-fns o))) 54 | 55 | (deftest test-formatter 56 | (let [formatter (. DateTimeFormatter ofPattern "yyyy MM dd") 57 | date (. LocalDate now) 58 | text (. date format formatter) 59 | parsed (. LocalDate parse text formatter)] 60 | (is (= date parsed)))) 61 | 62 | (def chrono-field-fmt 63 | (-> (new DateTimeFormatterBuilder) 64 | (.appendLiteral "Date is: ") 65 | (.appendValue (.. ChronoField -DAY_OF_YEAR) 3) 66 | (.appendValue (.. ChronoField -YEAR) 4) 67 | (.toFormatter))) 68 | 69 | (deftest test-formatter-builder 70 | (let [date (. LocalDate now) 71 | text (. date format chrono-field-fmt) 72 | parsed (. LocalDate parse text chrono-field-fmt)] 73 | (is (= date parsed)))) 74 | 75 | (def iso-field-fmt 76 | (-> (new DateTimeFormatterBuilder) 77 | (.appendValue (.. IsoFields -DAY_OF_QUARTER) 2) 78 | (.appendValue (.. IsoFields -QUARTER_OF_YEAR) 1) 79 | (.appendValue (.. ChronoField -YEAR) 4) 80 | (.toFormatter) 81 | (.withResolverStyle (. ResolverStyle -SMART)))) 82 | 83 | (deftest iso-formatter 84 | (let [date (. LocalDate of 2019 07 13) 85 | text (. date format iso-field-fmt)] 86 | (is (= text "1332019")))) 87 | -------------------------------------------------------------------------------- /web-target/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henryw374/cljs.java-time/952ac9aaa0bb537cd88cf2eb9e0c88612c9275aa/web-target/public/.gitkeep --------------------------------------------------------------------------------