Skip to content

Commit 6e16860

Browse files
committed
#5, 0.3.0 bump, legacy java type conversions
1 parent 00e4c6c commit 6e16860

File tree

6 files changed

+170
-22
lines changed

6 files changed

+170
-22
lines changed

Diff for: CHANGELOG.md

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
## 0.3.0
22

3-
### Fixed
3+
### Breaking changes
4+
5+
* `to-sql-date` converts anything convertible to `LocalDate` into a `java.sql.Date`.
6+
Previously `to-sql-date` returned a `java.util.Date` (bug).
7+
8+
### New Features
9+
10+
Please see a new section within README - [Legacy Date-Time
11+
Types](https://github.com/dm3/clojure.java-time#legacy-date-time-types)
412

5-
* *Breaking*: `to-sql-date` converts anything convertible to `LocalDate` into a `java.sql.Date`.
6-
Previously `to-sql-date` worked the same as `to-java-date`.
13+
* `java-date`, `sql-date`, `sql-timestamp`, `sql-time` - functions which
14+
product the `java.util.*` date-time objects.
15+
* [#5](https://github.com/dm3/clojure.java-time/issues/5) automatic conversions:
16+
- `java.sql.Date` -> `java.time.LocalDate`
17+
- `java.sql.Timestamp` -> `java.time.LocalDateTime`
18+
- `java.sql.Time` -> `java.time.LocalTime`
19+
* deprecated `to-java-date`/`to-sql-date`/`to-sql-timestamp`
720

821
## 0.2.2
922

Diff for: README.md

+58-17
Original file line numberDiff line numberDiff line change
@@ -312,18 +312,59 @@ less information, e.g. (assuming we're in UTC timezone):
312312
=> #object[java.time.LocalTime 0x3a3cd6d5 "01:00"]
313313
```
314314

315-
Any date which can be converted to an instant, can also be converted to pre-Java
316-
8 date types:
315+
#### Legacy Date-Time Types
317316

318-
```clj
319-
(to-java-date (zoned-date-time 2015 9 28))
317+
Any date which can be converted to an instant, can also be converted to a
318+
`java.util.Date`:
319+
320+
```clojure
321+
(java-date (zoned-date-time 2015 9 28))
320322
=> #inst "2015-09-27T22:00:00.000-00:00"
321323

322-
(to-sql-date (zoned-date-time 2015 9 28))
324+
(java-date 50000)
325+
=> #inst "1970-01-01T00:00:50.000-00:00"
326+
```
327+
328+
An instance of `java.util.Date` serves the same purpose as the new
329+
`java.time.Instant`. It's a machine timestamp which isn't aware of the
330+
timezone. Please, do not get confused by the way it is printed by the Clojure
331+
printer - the UTC timezone is applied during formatting.
332+
333+
Sometimes you'll have to work with the legacy `java.sql.Date/Time/Timestamp`
334+
types. The correspondence between the legacy types and the new Date-Time
335+
entities is as follows:
336+
337+
* `java.time.LocalDate` - `java.sql.Date`
338+
* `java.time.LocalDateTime` - `java.sql.Timestamp`
339+
* `java.time.LocalTime` - `java.sql.Time`
340+
341+
```clojure
342+
(sql-date 2015 9 28)
323343
=> #inst "2015-09-27T22:00:00.000-00:00"
324344

325-
(to-sql-timestamp (zoned-date-time 2015 9 28))
326-
=> #inst "2015-09-27T22:00:00.000000000-00:00"
345+
(sql-timestamp 2015 9 28 10 20 30 4000000)
346+
=> #inst "2015-09-28T09:20:30.004-00:00"
347+
348+
(sql-time 10 20 30)
349+
=> #inst "1970-01-01T09:20:30.000-00:00"
350+
```
351+
352+
The results of the above calls get printed as `#inst` because all of the
353+
`java.sql.Date/Time/Timestamp` are subtypes of `java.util.Date`.
354+
Coincidentally, this makes it impossible to plug the `java.sql.*` types into
355+
the Clojure.Java-Time conversion graph.
356+
357+
Conversions to the legacy types also go the other way around:
358+
359+
```clojure
360+
(j/local-date (j/sql-date 2015 9 28))
361+
#object[java.time.LocalDate "2015-09-28"]
362+
363+
(j/local-date-time (j/sql-timestamp 2015 9 28 10 20 30 4000000))
364+
#object[java.time.LocalDateTime "2015-09-28T10:20:30.004"]
365+
366+
(j/local-time (j/sql-time 10 20 30))
367+
#object[java.time.LocalTime "10:20:30"]
327368
```
328369

329370
#### Three-Ten Extra
@@ -335,7 +376,7 @@ project, you will get an `Interval`, `AmPm`, `DayOfMonth`, `DayOfYear`,
335376
An interval can be constructed from two entities that can be converted to
336377
instants:
337378

338-
```clj
379+
```clojure
339380
(interval (offset-date-time 2015 1 1) (zoned-date-time 2016 1 1))
340381
=> #<org.threeten.extra.Interval 2015-01-01T00:00:00Z/2016-01-01T00:00:00Z>
341382

@@ -354,7 +395,7 @@ instants:
354395
Bonus! if you have Joda Time on the classpath (either directly, or via
355396
`clj-time`), you can seamlessly convert from Joda Time to Java Time types:
356397

357-
```clj
398+
```clojure
358399
(java-time.repl/show-path org.joda.time.DateTime java.time.OffsetTime)
359400
=> {:cost 2.0,
360401
:path [[#<java_time.graph.Types@15e43c24 [org.joda.time.DateTime]>
@@ -374,7 +415,7 @@ you to influence the date-times create using default constructors ala Joda's
374415
`DateTimeUtils/setCurrentMillisSystem`. Clojure.Java-Time tries to fix that with
375416
the `with-clock` macro and the corresponding `with-clock-fn` function:
376417

377-
```clj
418+
```clojure
378419
(zone-id)
379420
=> #<java.time.ZoneRegion Europe/London>
380421

@@ -391,7 +432,7 @@ Date-Time entities are composed of date fields, while Duration entities are
391432
composed of time units. You can see all of the predefined fields and units
392433
via the `java-time.repl` ns:
393434

394-
```clj
435+
```clojure
395436
(java-time.repl/show-fields)
396437
=> (:aligned-day-of-week-in-month
397438
:aligned-day-of-week-in-year
@@ -402,7 +443,7 @@ via the `java-time.repl` ns:
402443
...)
403444
```
404445

405-
```clj
446+
```clojure
406447
(java-time.repl/show-units)
407448
=> (:centuries
408449
:days
@@ -415,7 +456,7 @@ via the `java-time.repl` ns:
415456

416457
You can obtain any field/unit like this:
417458

418-
```clj
459+
```clojure
419460
(field :year)
420461
=> #object[java.time.temporal.ChronoField "Year"]
421462

@@ -428,7 +469,7 @@ You can obtain any field/unit like this:
428469

429470
You can obtain all of the fields/units of the temporal entity:
430471

431-
```clj
472+
```clojure
432473
(fields (local-date))
433474
=> {:proleptic-month #object[java.time.temporal.ChronoField ...}
434475

@@ -441,7 +482,7 @@ By themselves the fields and units aren't very interesting. You can get the
441482
range of valid values for a field and a duration between two dates, but that's
442483
about it:
443484

444-
```clj
485+
```clojure
445486
(range (field :year))
446487
=> #object[java.time.temporal.ValueRange "-999999999 - 999999999"]
447488

@@ -458,7 +499,7 @@ are reasons for that which I feel are only valid in a statically-typed API like
458499
Java's. In Clojure, properties allow expressing time entity modifications and
459500
queries uniformly across all of the entity types.
460501

461-
```clj
502+
```clojure
462503
(def prop (property (local-date 2015 2 28) :day-of-month))
463504
=> #java_time.temporal.TemporalFieldProperty{...}
464505

@@ -496,7 +537,7 @@ Hopefully, the performance issue will be resolved in the future...
496537

497538
You can play with the conversion graph using the following helpers:
498539

499-
```clj
540+
```clojure
500541
(java-time.repl/show-path org.joda.time.DateTime java.time.OffsetTime)
501542
=> {:cost 2.0,
502543
:path [[#<java_time.graph.Types@15e43c24 [org.joda.time.DateTime]>

Diff for: project.clj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(defproject clojure.java-time "0.2.3-SNAPSHOT"
1+
(defproject clojure.java-time "0.3.0-SNAPSHOT"
22
:description "Clojure wrapper for Java 8 Time API"
33
:url "http://github.com/dm3/clojure.java-time"
44
:license {:name "MIT License"

Diff for: src/java_time.clj

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
(:require [java-time.potemkin.namespaces :as potemkin]
44
[java-time.util :as jt.u]
55
[java-time core properties temporal amount zone single-field local chrono
6-
convert sugar seqs adjuster interval format joda clock]))
6+
convert sugar seqs adjuster interval format joda clock pre-java8]))
77

88
(potemkin/import-vars
99
[java-time.clock
@@ -60,6 +60,9 @@
6060
[java-time.format
6161
format formatter]
6262

63+
[java-time.pre-java8
64+
java-date sql-date sql-timestamp sql-time]
65+
6366
[java-time.interval
6467
move-start-to move-end-to move-start-by move-end-by
6568
start end contains? overlaps? abuts? overlap gap])

Diff for: src/java_time/pre_java8.clj

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
(ns java-time.pre-java8
2+
(:require [java-time
3+
[local :as jt.l]
4+
[temporal :as jt.t]
5+
[defconversion :refer [conversion!]]]))
6+
7+
(defn ^java.util.Date java-date
8+
"Creates a `java.util.Date` out of any combination of arguments valid for
9+
`java-time/instant` or the Instant itself.
10+
11+
A `java.util.Date` represents an instant in time. It's a direct analog of the
12+
`java.time.Instant` type introduced in the JSR-310. Please consider using the
13+
`java.time.Instant` (through `java-time/instant`) directly."
14+
([] (java.util.Date/from (jt.t/instant)))
15+
([a] (java.util.Date/from (jt.t/instant a)))
16+
([a b] (java.util.Date/from (jt.t/instant a b))))
17+
18+
(defn- arities [type ctor n-args]
19+
(for [i (range (inc n-args))]
20+
(let [arg-vec (vec (take i (repeatedly gensym)))
21+
type-ctor (symbol (name type) "valueOf")]
22+
`(~arg-vec (~type-ctor (~ctor ~@arg-vec))))))
23+
24+
(defmacro defsqldate [type name ctor n-args doc]
25+
(let [fn-name (with-meta name {:tag type})]
26+
`(defn ~fn-name ~doc
27+
~@(arities type ctor n-args))))
28+
29+
(conversion! java.sql.Date java.time.LocalDate
30+
(fn [^java.sql.Date dt]
31+
(.toLocalDate dt)))
32+
33+
(conversion! java.sql.Timestamp java.time.LocalDateTime
34+
(fn [^java.sql.Timestamp dt]
35+
(.toLocalDateTime dt)))
36+
37+
(conversion! java.sql.Time java.time.LocalTime
38+
(fn [^java.sql.Time dt]
39+
(.toLocalTime dt)))
40+
41+
(defsqldate java.sql.Date sql-date jt.l/local-date 3
42+
"Creates a `java.sql.Date` out of any combination of arguments valid for
43+
`java-time/local-date` or the LocalDate itself.
44+
45+
Please consider using the JSR-310 Java Time types instead of `java.sql.Date`
46+
if your drivers support them.
47+
48+
Even though `java.sql.Date` extends a `java.util.Date`, it's supposed to be
49+
used as a local date (no time component or timezone) for the purposes of
50+
conversion from/to native JDBC driver DATE types.")
51+
52+
(defsqldate java.sql.Timestamp sql-timestamp jt.l/local-date-time 7
53+
"Creates a `java.sql.Timestamp` out of any combination of arguments valid for
54+
`java-time/local-date-time` or the LocalDateTime itself.
55+
56+
Please consider using the JSR-310 Java Time types instead of
57+
`java.sql.Timestamp` if your drivers support them.
58+
59+
`java.sql.Timestamp` is a version of a `java.util.Date` supposed to be used
60+
as a local date-time (no timezone) for the purposes of conversion from/to native
61+
JDBC driver TIMESTAMP types.")
62+
63+
(defsqldate java.sql.Time sql-time jt.l/local-time 3
64+
"Creates a `java.sql.Time` out of any combination of arguments valid for
65+
`java-time/local-time` (except the nanos constructor) or the LocalTime
66+
itself.
67+
68+
Please consider using the JSR-310 Java Time types instead of `java.sql.Time`
69+
if your drivers support them.
70+
71+
Even though `java.sql.Time` extends a `java.util.Date`, it's supposed to be
72+
used as a local time (no date component or timezone) for the purposes of
73+
conversion from/to native JDBC driver TIME types.")

Diff for: test/java_time_test.clj

+18
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,24 @@
617617
(is (= (java.util.Date. 1000) (j/to-java-date (j/instant 1000))))
618618
(is (= (java.sql.Date/valueOf (j/local-date 2016)) (j/to-sql-date (j/local-date 2016))))))
619619

620+
(testing "pre-java8"
621+
(is (= (j/java-date (j/instant 1000))
622+
(java.util.Date. 1000)
623+
(j/java-date 1000)))
624+
(is (= (java.sql.Date/valueOf (j/local-date 2000 10 5))
625+
(j/sql-date 2000 10 5)
626+
(j/sql-date (j/local-date 2000 10 5))))
627+
(is (= (java.sql.Timestamp/valueOf (j/local-date-time 2000 10 5 20 30 40))
628+
(j/sql-timestamp 2000 10 5 20 30 40)
629+
(j/sql-timestamp (j/local-date-time 2000 10 5 20 30 40))))
630+
(is (= (java.sql.Time/valueOf (j/local-time 20 30 40))
631+
(j/sql-time 20 30 40)
632+
(j/sql-time (j/local-time 20 30 40))))
633+
634+
(is (= (j/local-date 2000 10 5) (j/local-date (j/sql-date 2000 10 5))))
635+
(is (= (j/local-date-time 2000 10 5 20 30 40 1000)
636+
(j/local-date-time (j/sql-timestamp 2000 10 5 20 30 40 1000))))
637+
(is (= (j/local-time 20 30 40) (j/local-time (j/sql-time 20 30 40)))))
620638

621639
(testing "from java.util Date types"
622640
(is (= (j/zone-id "UTC") (j/zone-id (java.util.TimeZone/getTimeZone "UTC"))))))

0 commit comments

Comments
 (0)