|
| 1 | +/* |
| 2 | + * Copyright 2019-2024 JetBrains s.r.o. and contributors. |
| 3 | + * Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file. |
| 4 | + */ |
| 5 | +package kotlinx.datetime.test |
| 6 | + |
| 7 | +import kotlinx.datetime.* |
| 8 | +import kotlinx.datetime.internal.rulesForId |
| 9 | +import kotlin.math.roundToInt |
| 10 | +import kotlin.test.* |
| 11 | +import kotlin.time.Duration.Companion.milliseconds |
| 12 | +import kotlin.time.Duration.Companion.seconds |
| 13 | + |
| 14 | +class JsJodaTimezoneTest { |
| 15 | + @Test |
| 16 | + fun system() { |
| 17 | + val tz = TimeZone.currentSystemDefault() |
| 18 | + assertNotEquals("SYSTEM", tz.id) |
| 19 | + val systemTz = TimeZone.of("SYSTEM") |
| 20 | + assertEquals(tz, systemTz) |
| 21 | + assertEquals(tz.id, systemTz.id) |
| 22 | + } |
| 23 | + |
| 24 | + @Test |
| 25 | + fun iterateOverAllTimezones() { |
| 26 | + for (id in TimeZone.availableZoneIds) { |
| 27 | + val rules = rulesForId(id) ?: throw AssertionError("No rules for $id") |
| 28 | + val jodaZone = kotlinx.datetime.test.JSJoda.ZoneId.of(id) |
| 29 | + assertNull(rules.recurringZoneRules) |
| 30 | + fun checkAtInstant(instant: Instant) { |
| 31 | + val jodaInstant = kotlinx.datetime.test.JSJoda.Instant.ofEpochMilli(instant.toEpochMilliseconds().toDouble()) |
| 32 | + val zdt = jodaInstant.atZone(jodaZone) |
| 33 | + val offset = rules.infoAtInstant(instant) |
| 34 | + val ourLdt = instant.toLocalDateTime(offset) |
| 35 | + val theirLdt = LocalDateTime( |
| 36 | + zdt.year(), |
| 37 | + zdt.monthValue(), |
| 38 | + zdt.dayOfMonth(), |
| 39 | + zdt.hour(), |
| 40 | + zdt.minute(), |
| 41 | + zdt.second(), |
| 42 | + zdt.nano().roundToInt() |
| 43 | + ) |
| 44 | + if ((ourLdt.toInstant(TimeZone.UTC) - theirLdt.toInstant(TimeZone.UTC)).absoluteValue > 1.seconds) { |
| 45 | + // It seems that sometimes, js-joda interprets its data incorrectly by at most one second, |
| 46 | + // and we don't want to replicate that. |
| 47 | + // Example: America/Noronha at 1914-01-01T02:09:39.998Z: |
| 48 | + // - Computed 1913-12-31T23:59:59.998 with offset -02:09:40 |
| 49 | + // - 1914-01-01T00:00:00.998-02:09:39[America/Noronha] is js-joda's interpretation |
| 50 | + // The raw data representing the offset is `29.E`, which is `2 * 60 + 9 + (ord 'E' - 29) / 60`, |
| 51 | + // and `ord 'E'` is 69, so the offset is -2:09:40. |
| 52 | + // Thus, we allow a difference of 1 second. |
| 53 | + throw AssertionError("Failed for $id at $instant: computed $ourLdt with offset $offset, but $zdt is correct") |
| 54 | + } |
| 55 | + } |
| 56 | + fun checkTransition(instant: Instant) { |
| 57 | + checkAtInstant(instant - 2.milliseconds) |
| 58 | + checkAtInstant(instant) |
| 59 | + } |
| 60 | + // check historical data |
| 61 | + for (transition in rules.transitionEpochSeconds) { |
| 62 | + checkTransition(Instant.fromEpochSeconds(transition)) |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | +} |
0 commit comments