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