1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
(import date/native)
(defn time
`Return an opaque datetime representation of the current moment.`
[]
(native/time))
(defn time?
`Check if x is a date/time object.`
[x]
(= :date/time (type x)))
(defn tm?
`Check if x is a date/tm object.`
[x]
(= :date/tm (type x)))
(defn- callable?
[x]
(or (function? x) (cfunction? x))) # callable abstracts are hard to detect
(defn- map-pairs
[ds fun]
(->> ds
pairs
(map fun)
from-pairs))
(defn- put-date
[ds key val]
(assert (tm? ds))
(assert val)
(if (callable? val)
(update ds key val)
(put ds key val)))
(defn update-time!
```
Update a given date/time object as a whole.
If nil is passed as time, the function will call (date/time) for you.
This version will give you the corresponding timegm date/tm object to mutate
as you see fit. This is dangerous and not perfectly portable.
Use at your own peril.
Don't forget to return the resulting object, as it will be normalized and
transformed back into a date/time object for you.
```
[time fun]
(default time (native/time))
(assert (time? time))
(assert (callable? fun))
(def newtm (fun (:gmtime time)))
(:timegm! newtm)) # timegm! is slightly more efficient and we're discarding it
(defn update-time*
`Variant of update-time that takes a dictionary.`
[time ds]
(assert (dictionary? ds))
(update-time! time (fn [tm]
(eachp [k v] ds (put-date tm k v))
tm)))
(defn update-time
```
Update a given date/time object.
This takes a value for seconds, minutes, hours, day-of-month, month, and year.
The value may either be callable, in which case it will be given the old value
as an argument, and the return value will be used, or a value, in which case
it will be used as-is. Note that the resulting values need not be in any given
range, as they will be normalized.
It will automatically re-determine if DST is applicable and give you back a
modified date/time object.
If you need additional control over the underlying gmtime tm call, use
`update-time*` or `update-time!`.
You can pass `nil` as `time`, in which case the current time will be used.
Combined with specifying all the fields allows you to construct date/time
objects in UTC.
```
[time &keys {:sec second
:min minute
:hour hour
:mday month-day
:mon month
:year year}]
(update-time* time {:sec second
:min minute
:hour hour
:mday month-day
:mon month
:year year
:isdst :detect}))
|