@@ -168,33 +168,39 @@ public actual class Instant internal constructor(public actual val epochSeconds:
168
168
169
169
}
170
170
171
- private fun Instant.toZonedDateTimeFailing ( zone : TimeZone ): ZonedDateTime = try {
172
- toZonedDateTime(zone )
171
+ private fun Instant.toLocalDateTimeFailing ( offset : UtcOffset ): LocalDateTime = try {
172
+ toLocalDateTimeImpl(offset )
173
173
} catch (e: IllegalArgumentException ) {
174
174
throw DateTimeArithmeticException (" Can not convert instant $this to LocalDateTime to perform computations" , e)
175
175
}
176
176
177
- /* *
178
- * @throws IllegalArgumentException if the [Instant] exceeds the boundaries of [LocalDateTime]
179
- */
180
- private fun Instant.toZonedDateTime (zone : TimeZone ): ZonedDateTime {
181
- val currentOffset = zone.offsetAt(this )
182
- return ZonedDateTime (toLocalDateTimeImpl(currentOffset), currentOffset)
183
- }
184
-
185
- /* * Check that [Instant] fits in [ZonedDateTime].
177
+ /* * Check that [Instant] fits in [LocalDateTime].
186
178
* This is done on the results of computations for consistency with other platforms.
187
179
*/
188
180
private fun Instant.check (zone : TimeZone ): Instant = this @check.also {
189
- toZonedDateTimeFailing( zone)
181
+ toLocalDateTimeFailing(offsetIn( zone) )
190
182
}
191
183
192
184
public actual fun Instant.plus (period : DateTimePeriod , timeZone : TimeZone ): Instant = try {
193
185
with (period) {
194
- val withDate = toZonedDateTimeFailing(timeZone)
195
- .run { if (totalMonths != 0L ) timeZone.atZone(dateTime.plus(totalMonths, DateTimeUnit .MONTH ), offset) else this }
196
- .run { if (days != 0 ) timeZone.atZone(dateTime.plus(days, DateTimeUnit .DAY ), offset) else this }
197
- withDate.toInstant()
186
+ val initialOffset = offsetIn(timeZone)
187
+ val initialLdt = toLocalDateTimeFailing(initialOffset)
188
+ val offsetAfterMonths: UtcOffset
189
+ val ldtAfterMonths: LocalDateTime
190
+ if (totalMonths != 0L ) {
191
+ val (ldt, offset) = timeZone.atZone(initialLdt.plus(totalMonths, DateTimeUnit .MONTH ), initialOffset)
192
+ offsetAfterMonths = offset
193
+ ldtAfterMonths = ldt
194
+ } else {
195
+ offsetAfterMonths = initialOffset
196
+ ldtAfterMonths = initialLdt
197
+ }
198
+ val instantAfterMonthsAndDays = if (days != 0 ) {
199
+ timeZone.atZone(ldtAfterMonths.plus(days, DateTimeUnit .DAY ), offsetAfterMonths).toInstant()
200
+ } else {
201
+ ldtAfterMonths.toInstant(offsetAfterMonths)
202
+ }
203
+ instantAfterMonthsAndDays
198
204
.run { if (totalNanoseconds != 0L ) plus(0 , totalNanoseconds).check(timeZone) else this }
199
205
}.check(timeZone)
200
206
} catch (e: ArithmeticException ) {
@@ -213,11 +219,9 @@ public actual fun Instant.minus(value: Int, unit: DateTimeUnit, timeZone: TimeZo
213
219
public actual fun Instant.plus (value : Long , unit : DateTimeUnit , timeZone : TimeZone ): Instant = try {
214
220
when (unit) {
215
221
is DateTimeUnit .DateBased -> {
216
- val toZonedDateTimeFailing = toZonedDateTimeFailing(timeZone)
217
- timeZone.atZone(
218
- toZonedDateTimeFailing.dateTime.plus(value, unit),
219
- toZonedDateTimeFailing.offset
220
- ).toInstant()
222
+ val preferredOffset = offsetIn(timeZone)
223
+ val initialLdt = toLocalDateTimeFailing(preferredOffset)
224
+ timeZone.atZone(initialLdt.plus(value, unit), preferredOffset).toInstant()
221
225
}
222
226
is DateTimeUnit .TimeBased ->
223
227
check(timeZone).plus(value, unit).check(timeZone)
@@ -240,30 +244,23 @@ public actual fun Instant.plus(value: Long, unit: DateTimeUnit.TimeBased): Insta
240
244
}
241
245
242
246
public actual fun Instant.periodUntil (other : Instant , timeZone : TimeZone ): DateTimePeriod {
243
- var thisLdt = toZonedDateTimeFailing(timeZone)
244
- val otherLdt = other.toZonedDateTimeFailing(timeZone)
245
-
246
- val months = thisLdt.dateTime.until(otherLdt.dateTime, DateTimeUnit .MONTH ) // `until` on dates never fails
247
- thisLdt = timeZone.atZone(
248
- thisLdt.dateTime.plus(months, DateTimeUnit .MONTH ),
249
- thisLdt.offset
250
- ) // won't throw: thisLdt + months <= otherLdt, which is known to be valid
251
- val days =
252
- thisLdt.dateTime.until(otherLdt.dateTime, DateTimeUnit .DAY ) // `until` on dates never fails
253
- thisLdt = timeZone.atZone(
254
- thisLdt.dateTime.plus(days, DateTimeUnit .DAY ),
255
- thisLdt.offset
256
- ) // won't throw: thisLdt + days <= otherLdt
257
- val nanoseconds =
258
- thisLdt.toInstant().until(otherLdt.toInstant(), DateTimeUnit .NANOSECOND ) // |otherLdt - thisLdt| < 24h
247
+ val thisOffset1 = offsetIn(timeZone)
248
+ val thisLdt1 = toLocalDateTimeFailing(thisOffset1)
249
+ val otherLdt = other.toLocalDateTimeFailing(other.offsetIn(timeZone))
250
+
251
+ val months = thisLdt1.until(otherLdt, DateTimeUnit .MONTH ) // `until` on dates never fails
252
+ val (thisLdt2, thisOffset2) = timeZone.atZone(thisLdt1.plus(months, DateTimeUnit .MONTH ), thisOffset1) // won't throw: thisLdt + months <= otherLdt, which is known to be valid
253
+ val days = thisLdt2.until(otherLdt, DateTimeUnit .DAY ) // `until` on dates never fails
254
+ val (thisLdt3, thisOffset3) = timeZone.atZone(thisLdt2.plus(days, DateTimeUnit .DAY ), thisOffset2) // won't throw: thisLdt + days <= otherLdt
255
+ val nanoseconds = thisLdt3.toInstant(thisOffset3).until(other, DateTimeUnit .NANOSECOND ) // |otherLdt - thisLdt| < 24h
259
256
260
257
return buildDateTimePeriod(months, days.toInt(), nanoseconds)
261
258
}
262
259
263
260
public actual fun Instant.until (other : Instant , unit : DateTimeUnit , timeZone : TimeZone ): Long =
264
261
when (unit) {
265
262
is DateTimeUnit .DateBased ->
266
- toZonedDateTimeFailing( timeZone).dateTime. until(other.toZonedDateTimeFailing( timeZone).dateTime , unit)
263
+ toLocalDateTimeFailing(offsetIn( timeZone)). until(other.toLocalDateTimeFailing(other.offsetIn( timeZone)) , unit)
267
264
.toLong()
268
265
is DateTimeUnit .TimeBased -> {
269
266
check(timeZone); other.check(timeZone)
0 commit comments