Skip to content

Commit 6802cbb

Browse files
committed
squash! added missing Duration conversions from String, JavaDuration, Long/Int (by Claude)
1 parent f05abfe commit 6802cbb

3 files changed

Lines changed: 70 additions & 86 deletions

File tree

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/convert.kt

Lines changed: 23 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2927,126 +2927,73 @@ public fun <T> Convert<T, *>.toDateTimeComponents(): DataFrame<T> = asColumn { i
29272927
// region toDuration
29282928

29292929
/**
2930-
* Converts values in this [String] column to [Duration].
2930+
* Converts values in this column to [Duration].
29312931
*
2932-
* Parses each string using [Duration.parse].
2933-
* Fails with an exception if a value cannot be parsed.
2932+
* Supported source types: [String] (parsed via [Duration.parse]),
2933+
* [JavaDuration], [Long] and [Int] (interpreted as milliseconds).
29342934
*
29352935
* @return A new [DataColumn] with the [Duration] values.
29362936
*/
2937-
@JvmName("convertToDurationFromString")
2938-
public fun DataColumn<String>.convertToDuration(): DataColumn<Duration> = convertTo()
2937+
@JvmName("convertToDurationFromT")
2938+
public fun <T : Any> DataColumn<T>.convertToDuration(): DataColumn<Duration> = convertTo()
29392939

29402940
/**
2941-
* Converts values in this [String] column to [Duration]. Preserves null values.
2941+
* Converts values in this column to [Duration]. Preserves null values.
29422942
*
2943-
* Parses each string using [Duration.parse].
2944-
* Fails with an exception if a value cannot be parsed.
2943+
* Supported source types: [String] (parsed via [Duration.parse]),
2944+
* [JavaDuration], [Long] and [Int] (interpreted as milliseconds).
29452945
*
29462946
* @return A new [DataColumn] with the [Duration] nullable values.
29472947
*/
2948-
@JvmName("convertToDurationFromStringNullable")
2949-
public fun DataColumn<String?>.convertToDuration(): DataColumn<Duration?> = convertTo()
2950-
2951-
/**
2952-
* Converts values in this [JavaDuration] column to [Duration].
2953-
*
2954-
* @return A new [DataColumn] with the [Duration] values.
2955-
*/
2956-
@JvmName("convertToDurationFromJavaDuration")
2957-
public fun DataColumn<JavaDuration>.convertToDuration(): DataColumn<Duration> = convertTo()
2948+
public fun <T : Any> DataColumn<T?>.convertToDuration(): DataColumn<Duration?> = convertTo()
29582949

29592950
/**
2960-
* Converts values in this [JavaDuration] column to [Duration]. Preserves null values.
2961-
*
2962-
* @return A new [DataColumn] with the [Duration] nullable values.
2963-
*/
2964-
@JvmName("convertToDurationFromJavaDurationNullable")
2965-
public fun DataColumn<JavaDuration?>.convertToDuration(): DataColumn<Duration?> = convertTo()
2966-
2967-
/**
2968-
* Converts values in the [String] columns previously selected with [convert] to [Duration],
2951+
* Converts values in the columns previously selected with [convert] to [Duration],
29692952
* preserving their original names and positions within the [DataFrame].
2970-
* Preserves null values.
29712953
*
2972-
* Parses each string using [Duration.parse].
2973-
* Fails with an exception if a value cannot be parsed.
2954+
* Supported source types: [String] (parsed via [Duration.parse]),
2955+
* [JavaDuration], [Long] and [Int] (interpreted as milliseconds).
29742956
*
29752957
* For more information: {@include [DocumentationUrls.Convert]}
29762958
*
29772959
* ### Examples:
29782960
* ```kotlin
29792961
* df.convert { duration }.toDuration()
2962+
* df.convert { colsOf<String>() }.toDuration()
2963+
* df.convert { colsOf<Long>() }.toDuration()
29802964
* ```
29812965
*
29822966
* @return A new [DataFrame] with the values converted to [Duration].
29832967
*/
2984-
@JvmName("toDurationFromStringNullable")
2985-
@Refine
2986-
@Converter(Duration::class, nullable = true)
2987-
@Interpretable("ToSpecificType")
2988-
public fun <T> Convert<T, String?>.toDuration(): DataFrame<T> = asColumn { it.convertToDuration() }
2989-
2990-
/**
2991-
* Converts values in the [String] columns previously selected with [convert] to [Duration],
2992-
* preserving their original names and positions within the [DataFrame].
2993-
*
2994-
* Parses each string using [Duration.parse].
2995-
* Fails with an exception if a value cannot be parsed.
2996-
*
2997-
* For more information: {@include [DocumentationUrls.Convert]}
2998-
*
2999-
* ### Examples:
3000-
* ```kotlin
3001-
* df.convert { duration }.toDuration()
3002-
* ```
3003-
*
3004-
* @return A new [DataFrame] with the values converted to [Duration].
3005-
*/
3006-
@JvmName("toDurationFromString")
2968+
@JvmName("toDurationTAny")
30072969
@Refine
30082970
@Converter(Duration::class, nullable = false)
30092971
@Interpretable("ToSpecificType")
3010-
public fun <T> Convert<T, String>.toDuration(): DataFrame<T> = asColumn { it.convertToDuration() }
2972+
public fun <T> Convert<T, Any>.toDuration(): DataFrame<T> = to<Duration>()
30112973

30122974
/**
3013-
* Converts values in the [JavaDuration] columns previously selected with [convert] to [Duration],
2975+
* Converts values in the columns previously selected with [convert] to [Duration],
30142976
* preserving their original names and positions within the [DataFrame].
30152977
* Preserves null values.
30162978
*
3017-
* For more information: {@include [DocumentationUrls.Convert]}
3018-
*
3019-
* ### Examples:
3020-
* ```kotlin
3021-
* df.convert { duration }.toDuration()
3022-
* ```
3023-
*
3024-
* @return A new [DataFrame] with the values converted to [Duration].
3025-
*/
3026-
@JvmName("toDurationFromJavaDurationNullable")
3027-
@Refine
3028-
@Converter(Duration::class, nullable = true)
3029-
@Interpretable("ToSpecificType")
3030-
public fun <T> Convert<T, JavaDuration?>.toDuration(): DataFrame<T> = asColumn { it.convertToDuration() }
3031-
3032-
/**
3033-
* Converts values in the [JavaDuration] columns previously selected with [convert] to [Duration],
3034-
* preserving their original names and positions within the [DataFrame].
2979+
* Supported source types: [String] (parsed via [Duration.parse]),
2980+
* [JavaDuration], [Long] and [Int] (interpreted as milliseconds).
30352981
*
30362982
* For more information: {@include [DocumentationUrls.Convert]}
30372983
*
30382984
* ### Examples:
30392985
* ```kotlin
30402986
* df.convert { duration }.toDuration()
2987+
* df.convert { colsOf<String?>() }.toDuration()
2988+
* df.convert { colsOf<Long?>() }.toDuration()
30412989
* ```
30422990
*
30432991
* @return A new [DataFrame] with the values converted to [Duration].
30442992
*/
3045-
@JvmName("toDurationFromJavaDuration")
30462993
@Refine
3047-
@Converter(Duration::class, nullable = false)
2994+
@Converter(Duration::class, nullable = true)
30482995
@Interpretable("ToSpecificType")
3049-
public fun <T> Convert<T, JavaDuration>.toDuration(): DataFrame<T> = asColumn { it.convertToDuration() }
2996+
public fun <T> Convert<T, Any?>.toDuration(): DataFrame<T> = to<Duration?>()
30502997

30512998
// endregion
30522999

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/convert.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import kotlin.reflect.full.withNullability
5959
import kotlin.reflect.jvm.jvmErasure
6060
import kotlin.reflect.typeOf
6161
import kotlin.time.Duration
62+
import kotlin.time.Duration.Companion.milliseconds
6263
import kotlin.time.toJavaDuration
6364
import kotlin.time.toJavaInstant
6465
import kotlin.time.toKotlinDuration
@@ -273,11 +274,18 @@ internal fun createConverter(from: KType, to: KType, options: ParserOptions? = n
273274
toClass == Duration::class -> when (fromClass) {
274275
String::class -> Parsers.getAsConverterOrNull(to, options)!!
275276
JavaDuration::class -> convert<JavaDuration> { it.toKotlinDuration() }
277+
Long::class -> convert<Long> { it.milliseconds }
278+
Int::class -> convert<Int> { it.milliseconds }
276279
else -> null
277280
}
278281

279-
fromClass == Duration::class && toClass == JavaDuration::class ->
280-
convert<Duration> { it.toJavaDuration() }
282+
fromClass == Duration::class -> when (toClass) {
283+
JavaDuration::class -> convert<Duration> { it.toJavaDuration() }
284+
Long::class -> convert<Duration> { it.inWholeMilliseconds }
285+
Int::class -> convert<Duration> { it.inWholeMilliseconds.toInt() }
286+
String::class -> convert<Duration> { it.toString() }
287+
else -> null
288+
}
281289

282290
toClass.isValue -> {
283291
val constructor =

core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/convert.kt

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import kotlin.reflect.full.starProjectedType
2828
import kotlin.reflect.typeOf
2929
import kotlin.time.Duration
3030
import kotlin.time.Duration.Companion.hours
31+
import kotlin.time.Duration.Companion.milliseconds
3132
import kotlin.time.Duration.Companion.minutes
3233
import kotlin.time.toKotlinDuration
3334
import java.time.Duration as JavaDuration
@@ -375,31 +376,59 @@ class ConvertTests {
375376
@Test
376377
fun `toDuration from String column`() {
377378
val duration by columnOf("1h", "30m")
378-
val df = duration.toDataFrame()
379-
df.convert { duration }.toDuration()[{ "duration"<Duration>() }][0] shouldBe 1.hours
379+
duration.toDataFrame().convert { duration }.toDuration()["duration"][0] shouldBe 1.hours
380380
}
381381

382382
@Test
383383
fun `toDuration from nullable String column`() {
384384
val duration by columnOf("1h", null)
385-
val df = duration.toDataFrame()
386-
df.convert { duration }.toDuration()[{ "duration"<Duration?>() }].hasNulls shouldBe true
385+
duration.toDataFrame().convert { duration }.toDuration()["duration"].hasNulls shouldBe true
387386
}
388387

389388
@Test
390389
fun `toDuration from JavaDuration column`() {
391390
val javaDuration = JavaDuration.ofHours(2)
392391
val duration by columnOf(javaDuration)
393-
val df = duration.toDataFrame()
394-
df.convert { duration }.toDuration()[{ "duration"<Duration>() }][0] shouldBe javaDuration.toKotlinDuration()
392+
duration.toDataFrame().convert { duration }.toDuration()["duration"][0] shouldBe javaDuration.toKotlinDuration()
395393
}
396394

397395
@Test
398396
fun `toDuration from nullable JavaDuration column`() {
399397
val javaDuration = JavaDuration.ofMinutes(45)
400398
val duration by columnOf(javaDuration, null)
401-
val df = duration.toDataFrame()
402-
df.convert { duration }.toDuration()[{ "duration"<Duration?>() }][0] shouldBe javaDuration.toKotlinDuration()
399+
duration.toDataFrame().convert { duration }.toDuration()["duration"][0] shouldBe javaDuration.toKotlinDuration()
400+
}
401+
402+
@Test
403+
fun `toDuration from Long column`() {
404+
val duration by columnOf(3600_000L, 1800_000L)
405+
duration.toDataFrame().convert { duration }.toDuration()["duration"][0] shouldBe 1.hours
406+
}
407+
408+
@Test
409+
fun `toDuration from Int column`() {
410+
val duration by columnOf(3600_000, 1800_000)
411+
duration.toDataFrame().convert { duration }.toDuration()["duration"][0] shouldBe 1.hours
412+
}
413+
414+
@Test
415+
fun `Duration roundtrip via Long`() {
416+
val col = columnOf(1.hours, 30.minutes)
417+
col.convertToLong() shouldBe columnOf(3600_000L, 1800_000L)
418+
col.convertToLong().convertToDuration() shouldBe col
419+
}
420+
421+
@Test
422+
fun `Duration roundtrip via Int`() {
423+
val col = columnOf(1.hours, 30.minutes)
424+
col.convertToInt() shouldBe columnOf(3600_000, 1800_000)
425+
col.convertToInt().convertToDuration() shouldBe col
426+
}
427+
428+
@Test
429+
fun `Duration roundtrip via JavaDuration`() {
430+
val col = columnOf(1.hours)
431+
col.convertTo<JavaDuration>().convertToDuration() shouldBe col
403432
}
404433

405434
private interface Marker

0 commit comments

Comments
 (0)