Skip to content

Commit

Permalink
LocalDateTime regression JetBrains#1028
Browse files Browse the repository at this point in the history
  • Loading branch information
Tapac authored and SchweinchenFuntik committed Oct 23, 2021
1 parent 57d2e43 commit ab3c47b
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ class JavaLocalDateTimeColumnType : ColumnType(), IDateColumnType {
override fun notNullValueToDB(value: Any): Any = when {
value is LocalDateTime && currentDialect is SQLiteDialect ->
SQLITE_AND_ORACLE_DATE_TIME_STRING_FORMATTER.format(value.atZone(ZoneId.systemDefault()))
value is LocalDateTime ->
java.sql.Timestamp(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli())
value is LocalDateTime -> {
val instant = value.atZone(ZoneId.systemDefault()).toInstant()
java.sql.Timestamp(instant.toEpochMilli()).apply { nanos = instant.nano }
}
else -> value
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import org.jetbrains.exposed.sql.tests.DatabaseTestsBase
import org.jetbrains.exposed.sql.tests.TestDB
import org.jetbrains.exposed.sql.tests.currentDialectTest
import org.jetbrains.exposed.sql.tests.shared.assertEquals
import org.jetbrains.exposed.sql.vendors.MysqlDialect
import org.jetbrains.exposed.sql.vendors.*
import org.junit.Test
import java.time.*
import java.time.temporal.Temporal
Expand Down Expand Up @@ -71,6 +71,22 @@ open class JavaTimeBaseTest : DatabaseTestsBase() {
}
}
}

@Test
fun `test storing LocalDateTime with nanos`() {
val TestDate = object : IntIdTable("TestLocalDateTime") {
val time = datetime("time")
}
withTables(TestDate) {
val dateTimeWithNanos = LocalDateTime.now().withNano(123)
TestDate.insert {
it[time] = dateTimeWithNanos
}

val dateTimeFromDB = TestDate.selectAll().single()[TestDate.time]
assertEqualDateTime(dateTimeWithNanos, dateTimeFromDB)
}
}
}

fun <T : Temporal> assertEqualDateTime(d1: T?, d2: T?) {
Expand All @@ -87,14 +103,21 @@ fun <T : Temporal> assertEqualDateTime(d1: T?, d2: T?) {
d1 is LocalTime && d2 is LocalTime && d2.nano == 0 -> assertEquals<LocalTime>(d1.withNano(0), d2, "Failed on ${currentDialectTest.name}")
d1 is LocalTime && d2 is LocalTime -> assertEquals<LocalTime>(d1, d2, "Failed on ${currentDialectTest.name}")
d1 is LocalDateTime && d2 is LocalDateTime -> {
val d1Millis = Instant.from(d1.atZone(ZoneId.systemDefault())).toEpochMilli()
val d2Millis = Instant.from(d2.atZone(ZoneId.systemDefault())).toEpochMilli()
assertEquals(d1Millis, d2Millis, "Failed on ${currentDialectTest.name}")
val d1Nanos = currentDialectTest.extractNanos(d1)
val d2Nanos = currentDialectTest.extractNanos(d1)
assertEquals(d1.second + d1Nanos, d2.second + d2Nanos, "Failed on ${currentDialectTest.name}")
}
else -> assertEquals(d1, d2, "Failed on ${currentDialectTest.name}")
}
}

private fun DatabaseDialect.extractNanos(dt: LocalDateTime) = when (this) {
is MysqlDialect -> dt.nano.toString().take(6).toInt() // 1000000 ns
is SQLiteDialect -> 0
is PostgreSQLDialect -> dt.nano.toString().take(1).toInt() // 1 ms
else -> dt.nano
}

fun equalDateTime(d1: Temporal?, d2: Temporal?) = try {
assertEqualDateTime(d1, d2)
true
Expand Down

0 comments on commit ab3c47b

Please sign in to comment.