Skip to content

Commit de80ba9

Browse files
committed
Remove ZonedDateTime from the Native implementation
1 parent f7fb98c commit de80ba9

File tree

6 files changed

+37
-49
lines changed

6 files changed

+37
-49
lines changed

core/commonJs/src/internal/Platform.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,21 @@ private object SystemTimeZone: TimeZone() {
9696

9797
/* https://github.com/js-joda/js-joda/blob/8c1a7448db92ca014417346049fb64b55f7b1ac1/packages/core/src/LocalDate.js#L1404-L1416 +
9898
* https://github.com/js-joda/js-joda/blob/8c1a7448db92ca014417346049fb64b55f7b1ac1/packages/core/src/zone/SystemDefaultZoneRules.js#L69-L71 */
99-
override fun atStartOfDay(date: LocalDate): Instant = atZone(date.atTime(LocalTime.MIN)).toInstant()
99+
override fun atStartOfDay(date: LocalDate): Instant = localDateTimeToInstant(date.atTime(LocalTime.MIN))
100100

101101
/* https://github.com/js-joda/js-joda/blob/8c1a7448db92ca014417346049fb64b55f7b1ac1/packages/core/src/zone/SystemDefaultZoneRules.js#L21-L24 */
102102
override fun offsetAtImpl(instant: Instant): UtcOffset =
103103
UtcOffset(minutes = -Date(instant.toEpochMilliseconds().toDouble()).getTimezoneOffset().toInt())
104104

105105
/* https://github.com/js-joda/js-joda/blob/8c1a7448db92ca014417346049fb64b55f7b1ac1/packages/core/src/zone/SystemDefaultZoneRules.js#L49-L55 */
106-
override fun atZone(dateTime: LocalDateTime, preferred: UtcOffset?): LocalDateTimeWithOffset {
106+
override fun localDateTimeToInstant(dateTime: LocalDateTime, preferred: UtcOffset?): Instant {
107107
val epochMilli = dateTime.toInstant(UTC).toEpochMilliseconds()
108108
val offsetInMinutesBeforePossibleTransition = Date(epochMilli.toDouble()).getTimezoneOffset().toInt()
109109
val epochMilliSystemZone = epochMilli +
110110
offsetInMinutesBeforePossibleTransition * SECONDS_PER_MINUTE * MILLIS_PER_ONE
111111
val offsetInMinutesAfterPossibleTransition = Date(epochMilliSystemZone.toDouble()).getTimezoneOffset().toInt()
112112
val offset = UtcOffset(minutes = -offsetInMinutesAfterPossibleTransition)
113-
return LocalDateTimeWithOffset(dateTime, offset)
113+
return dateTime.toInstant(offset)
114114
}
115115

116116
override fun equals(other: Any?): Boolean = other === this

core/commonKotlin/src/Instant.kt

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -181,20 +181,24 @@ public actual fun Instant.plus(period: DateTimePeriod, timeZone: TimeZone): Inst
181181
with(period) {
182182
val initialOffset = offsetIn(timeZone)
183183
val initialLdt = toLocalDateTimeFailing(initialOffset)
184+
val instantAfterMonths: Instant
184185
val offsetAfterMonths: UtcOffset
185186
val ldtAfterMonths: LocalDateTime
186187
if (totalMonths != 0L) {
187-
val (ldt, offset) = timeZone.atZone(initialLdt.plus(totalMonths, DateTimeUnit.MONTH), initialOffset)
188-
offsetAfterMonths = offset
189-
ldtAfterMonths = ldt
188+
val unresolvedLdtWithMonths = initialLdt.plus(totalMonths, DateTimeUnit.MONTH)
189+
instantAfterMonths = timeZone.localDateTimeToInstant(unresolvedLdtWithMonths, initialOffset)
190+
offsetAfterMonths = instantAfterMonths.offsetIn(timeZone)
191+
ldtAfterMonths = instantAfterMonths.toLocalDateTimeFailing(offsetAfterMonths)
190192
} else {
193+
instantAfterMonths = this@plus
191194
offsetAfterMonths = initialOffset
192195
ldtAfterMonths = initialLdt
193196
}
194197
val instantAfterMonthsAndDays = if (days != 0) {
195-
timeZone.atZone(ldtAfterMonths.plus(days, DateTimeUnit.DAY), offsetAfterMonths).toInstant()
198+
val unresolvedLdtWithDays = ldtAfterMonths.plus(days, DateTimeUnit.DAY)
199+
timeZone.localDateTimeToInstant(unresolvedLdtWithDays, offsetAfterMonths)
196200
} else {
197-
ldtAfterMonths.toInstant(offsetAfterMonths)
201+
instantAfterMonths
198202
}
199203
instantAfterMonthsAndDays
200204
.run { if (totalNanoseconds != 0L) plus(0, totalNanoseconds).check(timeZone) else this }
@@ -215,9 +219,9 @@ public actual fun Instant.minus(value: Int, unit: DateTimeUnit, timeZone: TimeZo
215219
public actual fun Instant.plus(value: Long, unit: DateTimeUnit, timeZone: TimeZone): Instant = try {
216220
when (unit) {
217221
is DateTimeUnit.DateBased -> {
218-
val preferredOffset = offsetIn(timeZone)
219-
val initialLdt = toLocalDateTimeFailing(preferredOffset)
220-
timeZone.atZone(initialLdt.plus(value, unit), preferredOffset).toInstant()
222+
val initialOffset = offsetIn(timeZone)
223+
val initialLdt = toLocalDateTimeFailing(initialOffset)
224+
timeZone.localDateTimeToInstant(initialLdt.plus(value, unit), preferred = initialOffset)
221225
}
222226
is DateTimeUnit.TimeBased ->
223227
check(timeZone).plus(value, unit).check(timeZone)
@@ -240,15 +244,21 @@ public actual fun Instant.plus(value: Long, unit: DateTimeUnit.TimeBased): Insta
240244
}
241245

242246
public actual fun Instant.periodUntil(other: Instant, timeZone: TimeZone): DateTimePeriod {
243-
val thisOffset1 = offsetIn(timeZone)
244-
val thisLdt1 = toLocalDateTimeFailing(thisOffset1)
247+
val initialOffset = offsetIn(timeZone)
248+
val initialLdt = toLocalDateTimeFailing(initialOffset)
245249
val otherLdt = other.toLocalDateTimeFailing(other.offsetIn(timeZone))
246250

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
251+
val months = initialLdt.until(otherLdt, DateTimeUnit.MONTH) // `until` on dates never fails
252+
val unresolvedLdtWithMonths = initialLdt.plus(months, DateTimeUnit.MONTH)
253+
// won't throw: thisLdt + months <= otherLdt, which is known to be valid
254+
val instantWithMonths = timeZone.localDateTimeToInstant(unresolvedLdtWithMonths, preferred = initialOffset)
255+
val offsetWithMonths = instantWithMonths.offsetIn(timeZone)
256+
val ldtWithMonths = instantWithMonths.toLocalDateTimeFailing(offsetWithMonths)
257+
val days = ldtWithMonths.until(otherLdt, DateTimeUnit.DAY) // `until` on dates never fails
258+
val unresolvedLdtWithDays = ldtWithMonths.plus(days, DateTimeUnit.DAY)
259+
val newInstant = timeZone.localDateTimeToInstant(unresolvedLdtWithDays, preferred = initialOffset)
260+
// won't throw: thisLdt + days <= otherLdt
261+
val nanoseconds = newInstant.until(other, DateTimeUnit.NANOSECOND) // |otherLdt - thisLdt| < 24h
252262

253263
return buildDateTimePeriod(months, days.toInt(), nanoseconds)
254264
}

core/commonKotlin/src/LocalDateTimeWithOffset.kt

Lines changed: 0 additions & 14 deletions
This file was deleted.

core/commonKotlin/src/TimeZone.kt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,7 @@ public actual open class TimeZone internal constructor() {
9191
throw DateTimeArithmeticException("Instant $instant is not representable as LocalDateTime.", e)
9292
}
9393

94-
internal open fun localDateTimeToInstant(dateTime: LocalDateTime): Instant =
95-
atZone(dateTime).toInstant()
96-
97-
internal open fun atZone(dateTime: LocalDateTime, preferred: UtcOffset? = null): LocalDateTimeWithOffset =
94+
internal open fun localDateTimeToInstant(dateTime: LocalDateTime, preferred: UtcOffset? = null): Instant =
9895
error("Should be overridden")
9996

10097
actual override fun equals(other: Any?): Boolean =
@@ -118,11 +115,10 @@ public actual class FixedOffsetTimeZone internal constructor(public actual val o
118115

119116
override fun offsetAtImpl(instant: Instant): UtcOffset = offset
120117

121-
override fun atZone(dateTime: LocalDateTime, preferred: UtcOffset?): LocalDateTimeWithOffset =
122-
LocalDateTimeWithOffset(dateTime, offset)
118+
override fun localDateTimeToInstant(dateTime: LocalDateTime, preferred: UtcOffset?): Instant =
119+
dateTime.toInstant(offset)
123120

124121
override fun instantToLocalDateTime(instant: Instant): LocalDateTime = instant.toLocalDateTime(offset)
125-
override fun localDateTimeToInstant(dateTime: LocalDateTime): Instant = dateTime.toInstant(offset)
126122
}
127123

128124

core/commonKotlin/src/internal/RegionTimeZone.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ internal class RegionTimeZone(private val tzid: TimeZoneRules, override val id:
1818
}
1919
}
2020

21-
override fun atZone(dateTime: LocalDateTime, preferred: UtcOffset?): LocalDateTimeWithOffset =
21+
override fun localDateTimeToInstant(dateTime: LocalDateTime, preferred: UtcOffset?): Instant =
2222
when (val info = tzid.infoAtDatetime(dateTime)) {
23-
is OffsetInfo.Regular -> LocalDateTimeWithOffset(dateTime, info.offset)
23+
is OffsetInfo.Regular -> dateTime.toInstant(info.offset)
2424
is OffsetInfo.Gap -> {
2525
try {
26-
LocalDateTimeWithOffset(dateTime.plusSeconds(info.transitionDurationSeconds), info.offsetAfter)
26+
dateTime.plusSeconds(info.transitionDurationSeconds).toInstant(info.offsetAfter)
2727
} catch (e: IllegalArgumentException) {
2828
throw DateTimeArithmeticException(
2929
"Overflow whet correcting the date-time to not be in the transition gap",
@@ -32,8 +32,7 @@ internal class RegionTimeZone(private val tzid: TimeZoneRules, override val id:
3232
}
3333
}
3434

35-
is OffsetInfo.Overlap -> LocalDateTimeWithOffset(
36-
dateTime,
35+
is OffsetInfo.Overlap -> dateTime.toInstant(
3736
if (info.offsetAfter == preferred) info.offsetAfter else info.offsetBefore
3837
)
3938
}

core/commonKotlin/test/ThreeTenBpTimeZoneTest.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,14 @@ class ThreeTenBpTimeZoneTest {
3333
val t1 = LocalDateTime(2020, 3, 29, 2, 14, 17, 201)
3434
val t2 = LocalDateTime(2020, 3, 29, 3, 14, 17, 201)
3535
val tz = TimeZone.of("Europe/Berlin")
36-
assertEquals(tz.atZone(t1), tz.atZone(t2))
36+
assertEquals(tz.localDateTimeToInstant(t1), tz.localDateTimeToInstant(t2))
3737
}
3838

3939
@Test
4040
fun overlappingLocalTime() {
4141
val t = LocalDateTime(2007, 10, 28, 2, 30, 0, 0)
4242
val zone = TimeZone.of("Europe/Paris")
43-
assertEquals(LocalDateTimeWithOffset(
44-
LocalDateTime(2007, 10, 28, 2, 30, 0, 0),
45-
UtcOffset(seconds = 2 * 3600)
46-
), zone.atZone(t))
43+
assertEquals(t.toInstant(UtcOffset(hours = 2)), zone.localDateTimeToInstant(t))
4744
}
4845

4946
}

0 commit comments

Comments
 (0)