@@ -31,12 +31,15 @@ its scope. Internationalization (such as locale-specific month and day names) is
31
31
The library provides the basic set of types for working with date and time:
32
32
33
33
- ` Instant ` to represent a moment on the UTC-SLS time scale;
34
+ - ` Clock ` to obtain the current instant;
34
35
- ` LocalDateTime ` to represent date and time components without a reference to the particular time zone;
35
36
- ` LocalDate ` to represent the components of date only;
36
37
- ` TimeZone ` and ` ZoneOffset ` provide time zone information to convert between ` Instant ` and ` LocalDateTime ` ;
37
38
- ` Month ` and ` DayOfWeek ` enums;
38
- - ` CalendarPeriod ` to represent a difference between two instants decomposed into calendar units. The latter are
39
- listed in ` CalendarUnit ` enum.
39
+ - ` DateTimePeriod ` to represent a difference between two instants decomposed into date and time units;
40
+ - ` DatePeriod ` is a subclass of ` DateTimePeriod ` with zero time components,
41
+ it represents a difference between two LocalDate values decomposed into date units.
42
+ - ` DateTimeUnit ` provides a set of predefined date and time units to use in arithmetic operations on ` Instant ` and ` LocalDate ` .
40
43
41
44
### Type use-cases
42
45
@@ -50,7 +53,7 @@ Here is some basic advice on how to choose which of the date-carrying types to u
50
53
the scheduled event separately. Try to avoid converting future events to ` Instant ` in advance, because time-zone
51
54
rules might change unexpectedly in the future.
52
55
Also, use ` LocalDateTime ` to decode an ` Instant ` to its local date-time components for display and UIs.
53
- - Use ` LocalDate ` to represent a date of the event that does not have a specific time associated with it (like a birthday ).
56
+ - Use ` LocalDate ` to represent a date of the event that does not have a specific time associated with it (like a birth date ).
54
57
55
58
## Operations
56
59
@@ -60,12 +63,22 @@ With the above types you can get the following operations done.
60
63
### Getting the current moment of time
61
64
62
65
The current moment of time can be captured with the ` Instant ` type.
63
- Use ` Instant.now() ` function in its companion object.
66
+ To obtain an ` Instant ` corresponding to the current moment of time,
67
+ use ` now() ` function of the ` Clock ` interface:
64
68
65
69
``` kotlin
66
- val currentMoment = Instant .now()
70
+ val clock: Clock = .. .
71
+ val currentMoment = clock.now()
67
72
```
68
73
74
+ An instance of ` Clock ` can be injected through the function/class parameters,
75
+ or you can use its default implementation ` Clock.System ` that represents the system clock:
76
+
77
+ ``` kotlin
78
+ val currentMoment = Clock .System .now()
79
+ ```
80
+
81
+
69
82
### Converting an instant to local date and time components
70
83
71
84
` Instant ` is just a counter of high resolution time intervals since the beginning of time scale.
@@ -75,9 +88,9 @@ that represents date and time components without a reference to the particular t
75
88
The ` TimeZone ` type provides the rules to convert instants from and to date/time components.
76
89
77
90
``` kotlin
78
- val currentMoment: Instant = Instant .now()
91
+ val currentMoment: Instant = Clock . System .now()
79
92
val datetimeInUtc: LocalDateTime = currentMoment.toLocalDateTime(TimeZone .UTC )
80
- val datetimeInSystemZone: LocalDateTime = currentMoment.toLocalDateTime(TimeZone .SYSTEM )
93
+ val datetimeInSystemZone: LocalDateTime = currentMoment.toLocalDateTime(TimeZone .currentSystemDefault() )
81
94
```
82
95
83
96
` LocalDateTime ` instance exposes familiar components of the Gregorian calendar:
@@ -111,8 +124,10 @@ val kotlinReleaseInstant = kotlinReleaseDateTime.toInstant(TimeZone.of("UTC+3"))
111
124
by converting it to ` LocalDateTime ` and taking its ` date ` property.
112
125
113
126
``` kotlin
114
- val now: Instant = Instant .now()
115
- val today: LocalDate = now.toLocalDateTime(TimeZone .SYSTEM ).date
127
+ val now: Instant = Clock .System .now()
128
+ val today: LocalDate = now.toLocalDateTime(TimeZone .currentSystemDefault()).date
129
+ // or more short
130
+ val today: LocalDate = Clock .System .todayAt(TimeZone .currentSystemDefault())
116
131
```
117
132
Note, that today's date really depends on the time zone in which you're observing the current moment.
118
133
@@ -134,7 +149,7 @@ the `parse` function in companion object is used to parse a string representatio
134
149
135
150
136
151
``` kotlin
137
- val instantNow = Instant .now()
152
+ val instantNow = Clock . System .now()
138
153
instantNow.toString() // returns something like 2015-12-31T12:30:00Z
139
154
val instantBefore = Instant .parse(" 2010-06-01T22:19:44.475Z" )
140
155
```
@@ -155,7 +170,7 @@ where it feels more convenient:
155
170
### Instant arithmetic
156
171
157
172
``` kotlin
158
- val now = Instant .now()
173
+ val now = Clock . System .now()
159
174
val instantInThePast: Instant = Instant .parse(" 2020-01-01T00:00:00Z" )
160
175
val durationSinceThen: Duration = now - instantInThePast
161
176
val equidistantInstantInTheFuture: Instant = now + durationSinceThen
@@ -167,52 +182,59 @@ This type holds the amount of time that can be represented in different time uni
167
182
To get the calendar difference between two instants you can use ` Instant.periodUntil(Instant, TimeZone) ` function.
168
183
169
184
``` kotlin
170
- val period: CalendarPeriod = instantInThePast.periodUntil(Instant .now(), TimeZone .UTC )
185
+ val period: DateTimePeriod = instantInThePast.periodUntil(Clock . System .now(), TimeZone .UTC )
171
186
```
172
187
173
- ` CalendarPeriod ` represents a difference between two particular moments as a sum of calendar components,
188
+ ` DateTimePeriod ` represents a difference between two particular moments as a sum of calendar components,
174
189
like "2 years, 3 months, 10 days, and 22 hours".
175
190
176
- The difference can be calculated as an integer amount of specified calendar units:
191
+ The difference can be calculated as an integer amount of specified date or time units:
177
192
178
193
``` kotlin
179
- val diffInMonths = instantInThePast.until(Instant . now(), CalendarUnit .MONTH , TimeZone .UTC )
194
+ val diffInMonths = instantInThePast.until(Clock . System . now(), DateTimeUnit .MONTH , TimeZone .UTC )
180
195
```
181
196
There are also shortcuts ` yearsUntil(...) ` , ` monthsUntil(...) ` , and ` daysUntil(...) ` .
182
197
183
- A particular amount of calendar units or a calendar period can be added to an ` Instant ` with the ` plus ` function:
198
+ A particular amount of date/time units or a date/time period can be added to an ` Instant ` with the ` plus ` function:
184
199
185
200
``` kotlin
186
- val now = Instant .now()
187
- val tomorrow = now.plus(1 , CalendarUnit .DAY , TimeZone .SYSTEM )
188
- val threeYearsAndAMonthLater = now.plus(CalendarPeriod (years = 3 , months = 1 ), TimeZone .SYSTEM )
201
+ val now = Clock .System .now()
202
+ val systemTZ = TimeZone .currentSystemDefault()
203
+ val tomorrow = now.plus(2 , DateTimeUnit .DAY , systemTZ)
204
+ val threeYearsAndAMonthLater = now.plus(DateTimePeriod (years = 3 , months = 1 ), systemTZ)
189
205
```
190
206
191
207
Note that ` plus ` and ` ...until ` operations require ` TimeZone ` as a parameter because the calendar interval between
192
208
two particular instants can be different, when calculated in different time zones.
193
209
194
210
### Date arithmetic
195
211
196
- The similar operations with calendar units are provided for ` LocalDate ` type:
212
+ The similar operations with date units are provided for ` LocalDate ` type:
213
+
214
+ - ` LocalDate.plus(number, DateTimeUnit.DateBased) `
215
+ - ` LocalDate.plus(DatePeriod) `
216
+ - ` LocalDate.until(LocalDate, DateTimeUnit.DateBased) ` and the shortcuts ` yearsUntil ` , ` monthUntil ` , ` daysUntil `
217
+ - ` LocalDate.periodUntil(LocalDate): DatePeriod ` and ` LocalDate.minus(LocalDate): DatePeriod `
197
218
198
- - ` LocalDate.plus(number, CalendarUnit) `
199
- - ` LocalDate.plus(CalendarPeriod) `
200
- - ` LocalDate.periodUntil(LocalDate) ` and ` LocalDate.minus(LocalDate) `
219
+ Notice that instead of general ` DateTimeUnit ` and ` DateTimePeriod ` we're using their subtypes
220
+ ` DateTimeUnit.DateBased ` and ` DatePeriod ` respectively. This allows preventing the situations when
221
+ time components are being added to a date at compile time.
201
222
202
223
## Implementation
203
224
204
225
The implementation of date/time types, such as ` Instant ` , ` LocalDateTime ` , ` TimeZone ` and so on, relies on:
205
226
206
- - [ ` java.time ` ] ( https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html ) API in JVM;
207
- - [ ` js-joda ` ] ( https://js-joda.github.io/js-joda/ ) library in JS;
208
- - based on [ ThreeTen backport project] ( https://www.threeten.org/threetenbp/ ) in Native.
227
+ - in JVM: [ ` java.time ` ] ( https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html ) API;
228
+ - in JS: [ ` js-joda ` ] ( https://js-joda.github.io/js-joda/ ) library;
229
+ - in Native: based on [ ThreeTen backport project] ( https://www.threeten.org/threetenbp/ )
230
+ - time zone support is provided by [ date] ( https://github.com/HowardHinnant/date/ ) C++ library;
209
231
210
232
## Known/open issues, work TBD
211
233
212
- * Some kind of ` Clock ` interface is needed as a pluggable replacement for ` Instant.now() ` .
213
- * Flexible locale-neutral parsing and formatting facilities are needed to support various date/time interchange
234
+ - [x] Some kind of ` Clock ` interface is needed as a pluggable replacement for ` Instant.now() ` .
235
+ - [ ] Flexible locale-neutral parsing and formatting facilities are needed to support various date/time interchange
214
236
formats that are used in practice (in particular, various RFCs).
215
- * An alternative JVM implementation for Android might be needed.
237
+ - [ ] An alternative JVM implementation for Android might be needed.
216
238
217
239
## Building
218
240
0 commit comments