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