Skip to content

Commit 488c1f3

Browse files
committed
Remove ZonedDateTime from the Native implementation
1 parent 5634598 commit 488c1f3

File tree

6 files changed

+37
-49
lines changed

6 files changed

+37
-49
lines changed

core/commonJs/src/internal/Platform.kt

+3-3
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

+25-15
Original file line numberDiff line numberDiff line change
@@ -185,20 +185,24 @@ public actual fun Instant.plus(period: DateTimePeriod, timeZone: TimeZone): Inst
185185
with(period) {
186186
val initialOffset = offsetIn(timeZone)
187187
val initialLdt = toLocalDateTimeFailing(initialOffset)
188+
val instantAfterMonths: Instant
188189
val offsetAfterMonths: UtcOffset
189190
val ldtAfterMonths: LocalDateTime
190191
if (totalMonths != 0L) {
191-
val (ldt, offset) = timeZone.atZone(initialLdt.plus(totalMonths, DateTimeUnit.MONTH), initialOffset)
192-
offsetAfterMonths = offset
193-
ldtAfterMonths = ldt
192+
val unresolvedLdtWithMonths = initialLdt.plus(totalMonths, DateTimeUnit.MONTH)
193+
instantAfterMonths = timeZone.localDateTimeToInstant(unresolvedLdtWithMonths, initialOffset)
194+
offsetAfterMonths = instantAfterMonths.offsetIn(timeZone)
195+
ldtAfterMonths = instantAfterMonths.toLocalDateTimeFailing(offsetAfterMonths)
194196
} else {
197+
instantAfterMonths = this@plus
195198
offsetAfterMonths = initialOffset
196199
ldtAfterMonths = initialLdt
197200
}
198201
val instantAfterMonthsAndDays = if (days != 0) {
199-
timeZone.atZone(ldtAfterMonths.plus(days, DateTimeUnit.DAY), offsetAfterMonths).toInstant()
202+
val unresolvedLdtWithDays = ldtAfterMonths.plus(days, DateTimeUnit.DAY)
203+
timeZone.localDateTimeToInstant(unresolvedLdtWithDays, offsetAfterMonths)
200204
} else {
201-
ldtAfterMonths.toInstant(offsetAfterMonths)
205+
instantAfterMonths
202206
}
203207
instantAfterMonthsAndDays
204208
.run { if (totalNanoseconds != 0L) plus(0, totalNanoseconds).check(timeZone) else this }
@@ -219,9 +223,9 @@ public actual fun Instant.minus(value: Int, unit: DateTimeUnit, timeZone: TimeZo
219223
public actual fun Instant.plus(value: Long, unit: DateTimeUnit, timeZone: TimeZone): Instant = try {
220224
when (unit) {
221225
is DateTimeUnit.DateBased -> {
222-
val preferredOffset = offsetIn(timeZone)
223-
val initialLdt = toLocalDateTimeFailing(preferredOffset)
224-
timeZone.atZone(initialLdt.plus(value, unit), preferredOffset).toInstant()
226+
val initialOffset = offsetIn(timeZone)
227+
val initialLdt = toLocalDateTimeFailing(initialOffset)
228+
timeZone.localDateTimeToInstant(initialLdt.plus(value, unit), preferred = initialOffset)
225229
}
226230
is DateTimeUnit.TimeBased ->
227231
check(timeZone).plus(value, unit).check(timeZone)
@@ -244,15 +248,21 @@ public actual fun Instant.plus(value: Long, unit: DateTimeUnit.TimeBased): Insta
244248
}
245249

246250
public actual fun Instant.periodUntil(other: Instant, timeZone: TimeZone): DateTimePeriod {
247-
val thisOffset1 = offsetIn(timeZone)
248-
val thisLdt1 = toLocalDateTimeFailing(thisOffset1)
251+
val initialOffset = offsetIn(timeZone)
252+
val initialLdt = toLocalDateTimeFailing(initialOffset)
249253
val otherLdt = other.toLocalDateTimeFailing(other.offsetIn(timeZone))
250254

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

257267
return buildDateTimePeriod(months, days.toInt(), nanoseconds)
258268
}

core/commonKotlin/src/LocalDateTimeWithOffset.kt

-14
This file was deleted.

core/commonKotlin/src/TimeZone.kt

+3-7
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

+4-5
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

+2-5
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)