Skip to content

Commit 4f1544d

Browse files
committed
Add time zone detection tests.
1 parent 500964f commit 4f1544d

File tree

3 files changed

+86
-2
lines changed

3 files changed

+86
-2
lines changed

plot-api/src/commonMain/kotlin/org/jetbrains/letsPlot/intern/ToSpecConverters.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,10 @@ private fun inferSeriesDType(data: Any?): String {
453453
}
454454
}
455455

456-
private fun detectTimeZones(data: Any?): Map<String, String> {
456+
/**
457+
* Not private to allow access from tests
458+
*/
459+
internal fun detectTimeZones(data: Any?): Map<String, String> {
457460
return if (data is Map<*, *>) {
458461
@Suppress("UNCHECKED_CAST")
459462
data.entries

plot-api/src/commonMain/kotlin/org/jetbrains/letsPlot/intern/standardizing/Standardizing.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import org.jetbrains.letsPlot.commons.intern.datetime.Instant
1313
import org.jetbrains.letsPlot.commons.intern.datetime.Time
1414

1515
internal object Standardizing {
16-
// private val UTC_LP by lazy { TimeZone("UTC") }
1716

1817
fun standardizeValue(value: Any?): Any? {
1918
return when (value) {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2021. JetBrains s.r.o.
3+
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4+
*/
5+
6+
package org.jetbrains.letsPlot.intern.standardizing
7+
8+
import org.jetbrains.letsPlot.intern.detectTimeZones
9+
import java.time.OffsetDateTime
10+
import java.time.ZoneId
11+
import java.time.ZoneOffset
12+
import java.time.ZonedDateTime
13+
import kotlin.test.Test
14+
import kotlin.test.assertEquals
15+
import org.jetbrains.letsPlot.commons.intern.datetime.Instant as LPInstant
16+
import org.jetbrains.letsPlot.commons.intern.datetime.TimeZone as LPTimeZone
17+
18+
19+
class TimeZoneDetectionTest {
20+
21+
@Test
22+
fun `detected timezone is recognized`() {
23+
// This test verifies that:
24+
// 1. `detectTimeZones` correctly extracts timezone IDs from `ZonedDateTime` and `OffsetDateTime` objects.
25+
// 2. After standardizing to a timestamp and reconstructing with the detected timezone,
26+
// the resulting date-time components match the original objects.
27+
val zdtUtc = ZonedDateTime.of(2023, 1, 1, 10, 0, 0, 0, ZoneId.of("UTC"))
28+
val zdtMoscow = ZonedDateTime.of(2023, 1, 1, 10, 0, 0, 0, ZoneId.of("Europe/Moscow"))
29+
val zdtNewYork = ZonedDateTime.of(2023, 1, 1, 10, 0, 0, 0, ZoneId.of("America/New_York"))
30+
31+
val odtUtc = OffsetDateTime.of(2024, 2, 2, 12, 30, 0, 0, ZoneOffset.UTC)
32+
val odtMinus5h = OffsetDateTime.of(2024, 2, 2, 12, 30, 0, 0, ZoneOffset.ofHours(-5))
33+
val odtPlus5h30m = OffsetDateTime.of(2024, 2, 2, 12, 30, 0, 0, ZoneOffset.ofHoursMinutes(5, 30))
34+
35+
val testData = mapOf(
36+
"zdt_utc" to listOf(zdtUtc),
37+
"zdt_moscow" to listOf(zdtMoscow),
38+
"zdt_new_york" to listOf(zdtNewYork),
39+
"odt_utc" to listOf(odtUtc),
40+
"odt_minus_5h" to listOf(odtMinus5h),
41+
"odt_plus_5h_30m" to listOf(odtPlus5h30m)
42+
)
43+
44+
val detectedTimeZones = detectTimeZones(testData)
45+
46+
@Suppress("UNCHECKED_CAST")
47+
val standardizedData = Standardizing.standardizeValue(testData) as Map<String, List<Double>>
48+
49+
fun check(original: ZonedDateTime, key: String) {
50+
val timestamp = standardizedData.getValue(key).single()
51+
val tzId = detectedTimeZones.getValue(key)
52+
val lpDateTime = LPInstant(timestamp.toLong()).toDateTime(LPTimeZone(tzId))
53+
54+
assertEquals(original.year, lpDateTime.year)
55+
assertEquals(original.monthValue, lpDateTime.month.ordinal + 1)
56+
assertEquals(original.dayOfMonth, lpDateTime.day)
57+
assertEquals(original.hour, lpDateTime.time.hours)
58+
assertEquals(original.minute, lpDateTime.time.minutes)
59+
assertEquals(original.second, lpDateTime.time.seconds)
60+
}
61+
62+
fun check(original: OffsetDateTime, key: String) {
63+
val timestamp = standardizedData.getValue(key).single()
64+
val tzId = detectedTimeZones.getValue(key)
65+
val lpDateTime = LPInstant(timestamp.toLong()).toDateTime(LPTimeZone(tzId))
66+
67+
assertEquals(original.year, lpDateTime.year)
68+
assertEquals(original.monthValue, lpDateTime.month.ordinal + 1)
69+
assertEquals(original.dayOfMonth, lpDateTime.day)
70+
assertEquals(original.hour, lpDateTime.time.hours)
71+
assertEquals(original.minute, lpDateTime.time.minutes)
72+
assertEquals(original.second, lpDateTime.time.seconds)
73+
}
74+
75+
check(zdtUtc, "zdt_utc")
76+
check(zdtMoscow, "zdt_moscow")
77+
check(zdtNewYork, "zdt_new_york")
78+
check(odtUtc, "odt_utc")
79+
check(odtMinus5h, "odt_minus_5h")
80+
check(odtPlus5h30m, "odt_plus_5h_30m")
81+
}
82+
}

0 commit comments

Comments
 (0)