Skip to content

Commit

Permalink
Klock: Fixes Z parsing and adds DateTime.parseLocal as a shortcut for…
Browse files Browse the repository at this point in the history
… parse(str).local (#1640)

* Reproduces klock parsing problem

* Fixes klock Z parsing

* Adds DateFormat.parseLocal

* Updates test to use parseLocal
  • Loading branch information
soywiz authored May 29, 2023
1 parent 63101dc commit 7025b01
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 18 deletions.
1 change: 1 addition & 0 deletions klock/src/commonMain/kotlin/korlibs/time/DateFormat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fun DateFormat.parse(str: String, doAdjust: Boolean = true): DateTimeTz =
fun DateFormat.parseDate(str: String): Date = parse(str).local.date

fun DateFormat.parseUtc(str: String): DateTime = parse(str).utc
fun DateFormat.parseLocal(str: String): DateTime = parse(str).local

fun DateFormat.format(date: Double): String = format(DateTime.fromUnixMillis(date))
fun DateFormat.format(date: Long): String = format(DateTime.fromUnixMillis(date))
Expand Down
38 changes: 20 additions & 18 deletions klock/src/commonMain/kotlin/korlibs/time/PatternDateFormat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ data class PatternDateFormat @JvmOverloads constructor(
"SSSSSSS" -> """(\d{7})"""
"SSSSSSSS" -> """(\d{8})"""
"SSSSSSSSS" -> """(\d{9})"""
"X", "XX", "XXX", "x", "xx", "xxx" -> """([\w:\+\-]+)"""
"X", "XX", "XXX", "x", "xx", "xxx", "Z" -> """([\w:\+\-]+)"""
"a" -> """(\w+)"""
" " -> """(\s+)"""
else -> when {
Expand Down Expand Up @@ -244,24 +244,26 @@ data class PatternDateFormat @JvmOverloads constructor(
value.toInt()
}
}
"X", "XX", "XXX", "x", "xx", "xxx" -> when {
name.startsWith("X") && value.first() == 'Z' -> offset = 0.hours
name.startsWith("x") && value.first() == 'Z' -> {
if (doThrow) throw RuntimeException("Zulu Time Zone is only accepted with X-XXX formats.") else return null
}
value.first() != 'Z' -> {
val valueUnsigned = value.replace(":", "").removePrefix("-").removePrefix("+")
val hours = when (name.length) {
1 -> valueUnsigned.toInt()
else -> valueUnsigned.take(2).toInt()
}
val minutes = when (name.length) {
1 -> 0
else -> valueUnsigned.drop(2).toInt()
"X", "XX", "XXX", "x", "xx", "xxx" -> {
when {
name.startsWith("X") && value.first() == 'Z' -> offset = 0.hours
name.startsWith("x") && value.first() == 'Z' -> {
if (doThrow) throw RuntimeException("Zulu Time Zone is only accepted with X-XXX formats.") else return null
}
offset = hours.hours + minutes.minutes
if (value.first() == '-') {
offset = -offset
value.first() != 'Z' -> {
val valueUnsigned = value.replace(":", "").removePrefix("-").removePrefix("+")
val hours = when (name.length) {
1 -> valueUnsigned.toInt()
else -> valueUnsigned.take(2).toInt()
}
val minutes = when (name.length) {
1 -> 0
else -> valueUnsigned.drop(2).toInt()
}
offset = hours.hours + minutes.minutes
if (value.first() == '-') {
offset = -offset
}
}
}
}
Expand Down
50 changes: 50 additions & 0 deletions klock/src/jvmTest/kotlin/korlibs/time/JvmReferenceTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package korlibs.time

import java.time.*
import java.time.format.*
import kotlin.test.*

class JvmReferenceTest {
fun jvmParse(
pattern: String,
dateString: String
): Long {
val formatter = DateTimeFormatter.ofPattern(pattern)
val dateTime = LocalDateTime.parse(dateString, formatter);
val timestampMillis = dateTime.toInstant(ZoneOffset.UTC).toEpochMilli();
return timestampMillis
}

fun klockParse(
pattern: String,
dateString: String
): Long = DateFormat(pattern).parseLocal(dateString).unixMillisLong

@Test
fun testJvmParse() {
assertEquals(
1676679000000L,
jvmParse("EEE MMM dd HH:mm:ss Z yyyy", "Sat Feb 18 00:10:00 +0000 2023")
)
assertEquals(
1540124184000L,
jvmParse("EEE, dd MMM yyyy HH:mm:ss X", "Sun, 21 Oct 2018 12:16:24 +0300")
)
}

@Test
fun testKlockParseZ() {
assertEquals(
1676679000000L,
klockParse("EEE MMM dd HH:mm:ss Z yyyy", "Sat Feb 18 00:10:00 +0000 2023")
)
}

@Test
fun testKlockParseX() {
assertEquals(
1540124184000L,
klockParse("EEE, dd MMM yyyy HH:mm:ss X", "Sun, 21 Oct 2018 12:16:24 +0300")
)
}
}

0 comments on commit 7025b01

Please sign in to comment.