This is an automated email from the ASF dual-hosted git repository.
chenli pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git
The following commit(s) were added to refs/heads/main by this push:
new acca01d1d4 fix: support more java.time inputs in timestamp parsing
(#4139)
acca01d1d4 is described below
commit acca01d1d4974cba2b978b048f3e2c68782a56a9
Author: carloea2 <[email protected]>
AuthorDate: Sun Dec 28 20:45:30 2025 -0800
fix: support more java.time inputs in timestamp parsing (#4139)
### What changes were proposed in this PR?
* Added support in `parseTimestamp(fieldValue: Any)` for additional
`java.time` input types:
* `LocalDateTime` → `Timestamp.valueOf(ldt)`
* `Instant` → `Timestamp.from(inst)`
* `OffsetDateTime` → `Timestamp.from(odt.toInstant)`
* `ZonedDateTime` → `Timestamp.from(zdt.toInstant)`
* `LocalDate` → `Timestamp.valueOf(ld.atStartOfDay())`
### Any related issues, documentation, discussions?
* N/A.
### How was this PR tested?
* Added unit tests covering the new `java.time` cases for timestamp
parsing:
* Positive cases for `LocalDateTime`, `Instant`, `OffsetDateTime`,
`ZonedDateTime`, and `LocalDate`
* Negative case verifying unsupported/invalid inputs throw
`AttributeTypeException`
### Was this PR authored or co-authored using generative AI tooling?
No
---
.../amber/core/tuple/AttributeTypeUtils.scala | 13 +++++--
.../amber/core/tuple/AttributeTypeUtilsSpec.scala | 43 ++++++++++++++++++++--
2 files changed, 48 insertions(+), 8 deletions(-)
diff --git
a/common/workflow-core/src/main/scala/org/apache/texera/amber/core/tuple/AttributeTypeUtils.scala
b/common/workflow-core/src/main/scala/org/apache/texera/amber/core/tuple/AttributeTypeUtils.scala
index efb119e664..208f94d040 100644
---
a/common/workflow-core/src/main/scala/org/apache/texera/amber/core/tuple/AttributeTypeUtils.scala
+++
b/common/workflow-core/src/main/scala/org/apache/texera/amber/core/tuple/AttributeTypeUtils.scala
@@ -201,10 +201,15 @@ object AttributeTypeUtils extends Serializable {
def parseTimestamp(fieldValue: Any): Timestamp = {
val attempt: Try[Timestamp] = Try {
fieldValue match {
- case str: String => new
Timestamp(DateParserUtils.parseDate(str.trim).getTime)
- case long: java.lang.Long => new Timestamp(long)
- case timestamp: Timestamp => timestamp
- case date: java.util.Date => new Timestamp(date.getTime)
+ case str: String => new
Timestamp(DateParserUtils.parseDate(str.trim).getTime)
+ case long: java.lang.Long => new Timestamp(long)
+ case timestamp: Timestamp => timestamp
+ case date: java.util.Date => new
Timestamp(date.getTime)
+ case localDateTime: java.time.LocalDateTime =>
Timestamp.valueOf(localDateTime)
+ case instant: java.time.Instant =>
Timestamp.from(instant)
+ case offsetDateTime: java.time.OffsetDateTime =>
Timestamp.from(offsetDateTime.toInstant)
+ case zonedDateTime: java.time.ZonedDateTime =>
Timestamp.from(zonedDateTime.toInstant)
+ case localDate: java.time.LocalDate =>
Timestamp.valueOf(localDate.atStartOfDay())
// Integer, Double, Boolean, Binary are considered to be illegal here.
case _ =>
throw new AttributeTypeException(
diff --git
a/common/workflow-core/src/test/scala/org/apache/texera/amber/core/tuple/AttributeTypeUtilsSpec.scala
b/common/workflow-core/src/test/scala/org/apache/texera/amber/core/tuple/AttributeTypeUtilsSpec.scala
index 08b9774607..defa567480 100644
---
a/common/workflow-core/src/test/scala/org/apache/texera/amber/core/tuple/AttributeTypeUtilsSpec.scala
+++
b/common/workflow-core/src/test/scala/org/apache/texera/amber/core/tuple/AttributeTypeUtilsSpec.scala
@@ -22,17 +22,20 @@ package org.apache.texera.amber.core.tuple
import org.apache.texera.amber.core.tuple.AttributeType._
import org.apache.texera.amber.core.tuple.AttributeTypeUtils.{
AttributeTypeException,
+ add,
+ compare,
inferField,
inferSchemaFromRows,
- parseField,
- compare,
- add,
- minValue,
maxValue,
+ minValue,
+ parseField,
zeroValue
}
import org.scalatest.funsuite.AnyFunSuite
+import java.sql.Timestamp
+import java.time.{Instant, LocalDate, LocalDateTime, OffsetDateTime, ZoneId,
ZonedDateTime}
+
class AttributeTypeUtilsSpec extends AnyFunSuite {
// Unit Test for Infer Schema
@@ -179,9 +182,41 @@ class AttributeTypeUtilsSpec extends AnyFunSuite {
.getTime == 1699820130000L
)
+ val localDateTime = LocalDateTime.of(2023, 11, 13, 10, 15, 30)
+ val timestampFromLocalDateTime =
+ parseField(localDateTime,
AttributeType.TIMESTAMP).asInstanceOf[Timestamp]
+ assert(timestampFromLocalDateTime == Timestamp.valueOf(localDateTime))
+
+ val instant = Instant.parse("2023-11-13T10:15:30Z")
+ val timestampFromInstant = parseField(instant,
AttributeType.TIMESTAMP).asInstanceOf[Timestamp]
+ assert(timestampFromInstant == Timestamp.from(instant))
+
+ val offsetDateTime = OffsetDateTime.parse("2023-11-13T12:15:30+02:00")
+ val timestampFromOffsetDateTime =
+ parseField(offsetDateTime,
AttributeType.TIMESTAMP).asInstanceOf[Timestamp]
+ assert(timestampFromOffsetDateTime ==
Timestamp.from(offsetDateTime.toInstant))
+
+ val zonedDateTime =
+ ZonedDateTime.of(2023, 11, 13, 2, 15, 30, 0,
ZoneId.of("America/Los_Angeles"))
+ val timestampFromZonedDateTime =
+ parseField(zonedDateTime,
AttributeType.TIMESTAMP).asInstanceOf[Timestamp]
+ assert(timestampFromZonedDateTime ==
Timestamp.from(zonedDateTime.toInstant))
+
+ val localDate = LocalDate.of(2023, 11, 13)
+ val timestampFromLocalDate =
+ parseField(localDate, AttributeType.TIMESTAMP).asInstanceOf[Timestamp]
+ assert(timestampFromLocalDate ==
Timestamp.valueOf(localDate.atStartOfDay()))
+
+ val utilDate = new java.util.Date(1699820130000L)
+ val timestampFromDate = parseField(utilDate,
AttributeType.TIMESTAMP).asInstanceOf[Timestamp]
+ assert(timestampFromDate.getTime == 1699820130000L)
+
assertThrows[AttributeTypeException] {
parseField("invalid", AttributeType.TIMESTAMP)
}
+ assertThrows[AttributeTypeException] {
+ parseField(123.45, AttributeType.TIMESTAMP)
+ }
}
test("parseField correctly parses to STRING") {