This is an automated email from the ASF dual-hosted git repository.

MaxGekk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new ea066eaa3bdf [SPARK-57575][SQL] Support TIME type in 
to_char/to_varchar formatting
ea066eaa3bdf is described below

commit ea066eaa3bdf775a3bbdd514a6264f7adf2c096e
Author: Shrirang Mhalgi <[email protected]>
AuthorDate: Tue Jun 23 14:13:06 2026 +0200

    [SPARK-57575][SQL] Support TIME type in to_char/to_varchar formatting
    
    ### What changes were proposed in this pull request?
    Extend `DateFormatClass` (used by `to_char` / `to_varchar` / `date_format`) 
to accept `TimeType` input. When the input is `TimeType`, the expression uses 
`TimeFormatter` to format the time-of-day value instead of 
`TimestampFormatter`. Date-only pattern fields (e.g., `yyyy-MM-dd`) are 
rejected at runtime with a clear error.
    
    ### Why are the changes needed?
    to_char and to_varchar accept DateType and TimestampType but not TimeType. 
With the TIME data type now supported in Spark, users need a way to format time 
values to strings using standard datetime patterns (e.g., `to_char(time_col, 
'HH:mm:ss')`).
    
    ### Does this PR introduce _any_ user-facing change?
    Yes. `to_char(time_value, format)` and `to_varchar(time_value, format)` now 
work for TimeType inputs, formatting time-of-day fields (HH, mm, ss, fractional 
seconds). Passing date-only patterns to a TIME input raises an error.
    
    ### How was this patch tested?
    - Unit tests in `DateExpressionsSuite` (formatting, null handling, 
date-pattern rejection)
    - SQL golden file tests in `datetime-formatting.sql` verifying `to_char` 
and `to_varchar` with TIME literals
    - All existing `DateFormat` tests pass (no regressions)
    
    ### Was this patch authored or co-authored using generative AI tooling?
    Yes. Co-Authored using Claude Opus 4.6
    
    Closes #56637 from shrirangmhalgi/SPARK-57575-time-to-char.
    
    Authored-by: Shrirang Mhalgi <[email protected]>
    Signed-off-by: Max Gekk <[email protected]>
---
 .../catalyst/expressions/datetimeExpressions.scala | 108 ++++++++++++++++-----
 .../spark/sql/catalyst/optimizer/expressions.scala |   5 +-
 .../expressions/DateExpressionsSuite.scala         |  34 ++++++-
 .../SimplifyDateTimeConversionsSuite.scala         |  27 +++++-
 .../datetime-formatting-legacy.sql.out             |  14 +++
 .../analyzer-results/datetime-formatting.sql.out   |  14 +++
 .../sql-tests/inputs/datetime-formatting.sql       |   4 +
 .../results/datetime-formatting-legacy.sql.out     |  16 +++
 .../sql-tests/results/datetime-formatting.sql.out  |  16 +++
 9 files changed, 212 insertions(+), 26 deletions(-)

diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
index 3f773e5bb6dc..268d86852c3c 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
@@ -25,7 +25,7 @@ import java.util.Locale
 
 import org.apache.commons.text.StringEscapeUtils
 
-import org.apache.spark.{SparkException, SparkIllegalArgumentException}
+import org.apache.spark.{SparkException, SparkIllegalArgumentException, 
SparkRuntimeException}
 import org.apache.spark.sql.catalyst.InternalRow
 import org.apache.spark.sql.catalyst.analysis.{ExpressionBuilder, 
FunctionRegistry, TypeCheckResult}
 import 
org.apache.spark.sql.catalyst.analysis.TypeCheckResult.{DataTypeMismatch, 
TypeCheckSuccess}
@@ -35,7 +35,7 @@ import 
org.apache.spark.sql.catalyst.expressions.codegen.Block._
 import org.apache.spark.sql.catalyst.expressions.objects.StaticInvoke
 import org.apache.spark.sql.catalyst.trees.CurrentOrigin.withOrigin
 import org.apache.spark.sql.catalyst.trees.TreePattern._
-import org.apache.spark.sql.catalyst.util.{DateTimeUtils, LegacyDateFormats, 
TimestampFormatter}
+import org.apache.spark.sql.catalyst.util.{DateTimeUtils, LegacyDateFormats, 
TimeFormatter, TimestampFormatter}
 import org.apache.spark.sql.catalyst.util.DateTimeConstants._
 import org.apache.spark.sql.catalyst.util.DateTimeUtils._
 import org.apache.spark.sql.catalyst.util.LegacyDateFormats.SIMPLE_DATE_FORMAT
@@ -1231,34 +1231,76 @@ case class DateFormatClass(left: Expression, right: 
Expression, timeZoneId: Opti
   def this(left: Expression, right: Expression) = this(left, right, None)
 
   override def inputTypes: Seq[AbstractDataType] =
-    Seq(TimestampType, StringTypeWithCollation(supportsTrimCollation = true))
+    Seq(TypeCollection(TimestampType, AnyTimeType),
+      StringTypeWithCollation(supportsTrimCollation = true))
 
   override def withTimeZone(timeZoneId: String): TimeZoneAwareExpression =
     copy(timeZoneId = Option(timeZoneId))
 
   override protected def nullSafeEval(timestamp: Any, format: Any): Any = {
-    val formatter = formatterOption.getOrElse(getFormatter(format.toString))
-    UTF8String.fromString(formatter.format(timestamp.asInstanceOf[Long]))
+    left.dataType match {
+      case _: TimeType =>
+        val tf = timeFormatterOption.getOrElse(
+          TimeFormatter(format.toString, isParsing = false))
+        DateFormatClass.formatTimeWithError(
+          tf, timestamp.asInstanceOf[Long], prettyName, format.toString)
+      case _ =>
+        val formatter = 
formatterOption.getOrElse(getFormatter(format.toString))
+        UTF8String.fromString(formatter.format(timestamp.asInstanceOf[Long]))
+    }
   }
 
+  @transient private lazy val timeFormatterOption: Option[TimeFormatter] =
+    if (left.dataType.isInstanceOf[TimeType] && right.foldable) {
+      Option(right.eval()).map(fmt => TimeFormatter(fmt.toString, isParsing = 
false))
+    } else None
+
   override def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = {
-    formatterOption.map { tf =>
-      val timestampFormatter = ctx.addReferenceObj("timestampFormatter", tf)
-      defineCodeGen(ctx, ev, (timestamp, _) => {
-        s"""UTF8String.fromString($timestampFormatter.format($timestamp))"""
-      })
-    }.getOrElse {
-      val tf = TimestampFormatter.getClass.getName.stripSuffix("$")
-      val ldf = LegacyDateFormats.getClass.getName.stripSuffix("$")
-      val zid = ctx.addReferenceObj("zoneId", zoneId, classOf[ZoneId].getName)
-      defineCodeGen(ctx, ev, (timestamp, format) => {
-        s"""|UTF8String.fromString($tf$$.MODULE$$.apply(
-            |  $format.toString(),
-            |  $zid,
-            |  $ldf$$.MODULE$$.SIMPLE_DATE_FORMAT(),
-            |  false)
-            |.format($timestamp))""".stripMargin
-      })
+    left.dataType match {
+      case _: TimeType =>
+        timeFormatterOption.map { tf =>
+          val timeFormatter = ctx.addReferenceObj("timeFormatter", tf)
+          val funcName = ctx.addReferenceObj("funcName", prettyName)
+          val fmtStr = ctx.addReferenceObj("fmtStr", right.eval().toString)
+          defineCodeGen(ctx, ev, (time, _) => {
+            s"""|((org.apache.spark.unsafe.types.UTF8String)
+                |org.apache.spark.sql.catalyst.expressions
+                |.DateFormatClass.formatTimeWithError(
+                |$timeFormatter, $time,
+                |$funcName, $fmtStr))""".stripMargin.replaceAll("\n", "")
+          })
+        }.getOrElse {
+          val tf = TimeFormatter.getClass.getName.stripSuffix("$")
+          val funcName = ctx.addReferenceObj("funcName", prettyName)
+          defineCodeGen(ctx, ev, (time, format) => {
+            s"""|((org.apache.spark.unsafe.types.UTF8String)
+                |org.apache.spark.sql.catalyst.expressions
+                |.DateFormatClass.formatTimeWithError(
+                |$tf$$.MODULE$$.apply(
+                |$format.toString(), false),
+                |$time, $funcName,
+                |$format.toString()))""".stripMargin.replaceAll("\n", "")
+          })
+        }
+      case _ =>
+        formatterOption.map { tf =>
+          val timestampFormatter = ctx.addReferenceObj("timestampFormatter", 
tf)
+          defineCodeGen(ctx, ev, (timestamp, _) => {
+            
s"""UTF8String.fromString($timestampFormatter.format($timestamp))"""
+          })
+        }.getOrElse {
+          val tf = TimestampFormatter.getClass.getName.stripSuffix("$")
+          val ldf = LegacyDateFormats.getClass.getName.stripSuffix("$")
+          val zid = ctx.addReferenceObj("zoneId", zoneId, 
classOf[ZoneId].getName)
+          defineCodeGen(ctx, ev, (timestamp, format) => {
+            s"""|UTF8String.fromString($tf$$.MODULE$$.apply(
+                |  $format.toString(),
+                |  $zid,
+                |  $ldf$$.MODULE$$.SIMPLE_DATE_FORMAT(),
+                |  false)
+                |.format($timestamp))""".stripMargin
+          })
+        }
     }
   }
 
@@ -1275,6 +1317,28 @@ case class DateFormatClass(left: Expression, right: 
Expression, timeZoneId: Opti
   final override def nodePatternsInternal(): Seq[TreePattern] = Seq(DATETIME)
 }
 
+object DateFormatClass {
+  /**
+   * Formats a TIME value, mapping an invalid pattern to a Spark error.
+   * Used by both eval and codegen.
+   */
+  def formatTimeWithError(
+      tf: TimeFormatter, nanos: Long, funcName: String, pattern: String): 
UTF8String = {
+    try {
+      UTF8String.fromString(tf.format(nanos))
+    } catch {
+      case e: java.time.DateTimeException =>
+        throw new SparkRuntimeException(
+          errorClass = "INVALID_PARAMETER_VALUE.PATTERN",
+          messageParameters = Map(
+            "parameter" -> toSQLId("format"),
+            "functionName" -> toSQLId(funcName),
+            "value" -> toSQLValue(pattern, StringType)),
+          cause = e)
+    }
+  }
+}
+
 /**
  * Converts time string with given pattern.
  * Deterministic version of [[UnixTimestamp]], must have at least one 
parameter.
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/expressions.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/expressions.scala
index 929ffdef2b52..de847dddc935 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/expressions.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/expressions.scala
@@ -1207,7 +1207,7 @@ object SimplifyDateTimeConversions extends 
Rule[LogicalPlan] {
       // original string is in the same format.
       case DateFormatClass(
           GetTimestamp(
-            e @ DateFormatClass(_, pattern, timeZoneId),
+            e @ DateFormatClass(child, pattern, timeZoneId),
             pattern2,
             TimestampType,
             _,
@@ -1216,7 +1216,8 @@ object SimplifyDateTimeConversions extends 
Rule[LogicalPlan] {
           pattern3,
           timeZoneId3)
           if pattern.semanticEquals(pattern2) && 
pattern.semanticEquals(pattern3)
-            && timeZoneId == timeZoneId2 && timeZoneId == timeZoneId3 =>
+            && timeZoneId == timeZoneId2 && timeZoneId == timeZoneId3
+            && !child.dataType.isInstanceOf[TimeType] =>
         e
 
       // Remove a timestamp to string conversion followed by a string to 
timestamp conversions if
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
index 869cac60d7c6..4a016ee186bd 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
@@ -28,7 +28,7 @@ import scala.language.postfixOps
 import scala.reflect.ClassTag
 import scala.util.Random
 
-import org.apache.spark.{SparkArithmeticException, SparkDateTimeException, 
SparkFunSuite, SparkIllegalArgumentException, SparkUpgradeException}
+import org.apache.spark.{SparkArithmeticException, SparkDateTimeException, 
SparkFunSuite, SparkIllegalArgumentException, SparkRuntimeException, 
SparkUpgradeException}
 import org.apache.spark.sql.AnalysisException
 import org.apache.spark.sql.catalyst.{CatalystTypeConverters, InternalRow}
 import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.DataTypeMismatch
@@ -328,6 +328,38 @@ class DateExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
     }
   }
 
+  test("SPARK-57575: DateFormat with TimeType (to_char/to_varchar)") {
+    // 12:13:14 = (12*3600 + 13*60 + 14) seconds, stored as nanoseconds
+    val timeNanos = (12L * 3600 + 13 * 60 + 14) * 1000000000L
+    val timeLit = Literal.create(timeNanos, 
TimeType(TimeType.DEFAULT_PRECISION))
+
+    checkEvaluation(DateFormatClass(timeLit, Literal("HH:mm:ss"), UTC_OPT), 
"12:13:14")
+    checkEvaluation(DateFormatClass(timeLit, Literal("HH"), UTC_OPT), "12")
+    checkEvaluation(DateFormatClass(timeLit, Literal("mm"), UTC_OPT), "13")
+    checkEvaluation(DateFormatClass(timeLit, Literal("ss"), UTC_OPT), "14")
+
+    // Non-default precision (TIME(0)) should also work
+    val timeNanosLowPrec = (9L * 3600 + 30 * 60 + 0) * 1000000000L
+    val timeLitLowPrec = Literal.create(timeNanosLowPrec, TimeType(0))
+    checkEvaluation(DateFormatClass(timeLitLowPrec, Literal("HH:mm:ss"), 
UTC_OPT), "09:30:00")
+
+    // Null handling
+    checkEvaluation(
+      DateFormatClass(Literal.create(null, 
TimeType(TimeType.DEFAULT_PRECISION)),
+        Literal("HH:mm:ss"), UTC_OPT), null)
+
+    // Date-only pattern fields should error for TIME input with Spark error
+    val datePatternExpr = DateFormatClass(timeLit, Literal("yyyy-MM-dd"), 
UTC_OPT)
+    checkErrorInExpression[SparkRuntimeException](
+      datePatternExpr,
+      condition = "INVALID_PARAMETER_VALUE.PATTERN",
+      parameters = Map(
+        "parameter" -> "`format`",
+        "functionName" -> "`date_format`",
+        "value" -> "'yyyy-MM-dd'")
+    )
+  }
+
   test("Hour") {
     assert(Hour(Literal.create(null, DateType), UTC_OPT).resolved === false)
     assert(Hour(Literal(ts), UTC_OPT).resolved)
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/SimplifyDateTimeConversionsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/SimplifyDateTimeConversionsSuite.scala
index 8e7013f2df03..e67d8f2dc7f8 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/SimplifyDateTimeConversionsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/SimplifyDateTimeConversionsSuite.scala
@@ -19,7 +19,7 @@ package org.apache.spark.sql.catalyst.optimizer
 
 import org.apache.spark.sql.catalyst.dsl.expressions._
 import org.apache.spark.sql.catalyst.dsl.plans._
-import org.apache.spark.sql.catalyst.expressions.{DateFormatClass, 
GetTimestamp}
+import org.apache.spark.sql.catalyst.expressions.{AttributeReference, 
DateFormatClass, GetTimestamp}
 import org.apache.spark.sql.catalyst.plans.PlanTest
 import org.apache.spark.sql.catalyst.plans.logical._
 import org.apache.spark.sql.catalyst.rules.RuleExecutor
@@ -66,4 +66,29 @@ class SimplifyDateTimeConversionsSuite extends PlanTest {
 
     comparePlans(optimized, expected)
   }
+
+  test("SPARK-57575: SimplifyDateTimeConversions skips TimeType child") {
+    val timeAttr = AttributeReference("t", 
TimeType(TimeType.NANOS_PRECISION))()
+    val timeRelation = LocalRelation(timeAttr)
+    val pattern = "HH:mm:ss.SSSSSSSSS"
+
+    val df = DateFormatClass(timeAttr, pattern)
+
+    // date_format(to_timestamp(date_format(time_col, p), p), p) should NOT 
simplify
+    // because TIME(9) -> Timestamp truncates sub-micro precision (nanos lost)
+    val originalQuery = timeRelation
+      .select(
+        DateFormatClass(
+          GetTimestamp(
+            df,
+            pattern,
+            TimestampType),
+          pattern) as "c1")
+      .analyze
+
+    val optimized = Optimize.execute(originalQuery)
+
+    // Should NOT be simplified - optimized plan should equal original (no 
rewrite)
+    comparePlans(optimized, originalQuery)
+  }
 }
diff --git 
a/sql/core/src/test/resources/sql-tests/analyzer-results/datetime-formatting-legacy.sql.out
 
b/sql/core/src/test/resources/sql-tests/analyzer-results/datetime-formatting-legacy.sql.out
index 7c5f1260b648..b61a35681b0a 100644
--- 
a/sql/core/src/test/resources/sql-tests/analyzer-results/datetime-formatting-legacy.sql.out
+++ 
b/sql/core/src/test/resources/sql-tests/analyzer-results/datetime-formatting-legacy.sql.out
@@ -393,3 +393,17 @@ select date_format(timestamp_ntz'2023-08-18 
09:13:14.123456', 'yyyy-MM-dd HH:mm:
 -- !query analysis
 Project [date_format(cast(2023-08-18 09:13:14.123456 as timestamp), yyyy-MM-dd 
HH:mm:ss.SSSSSS, Some(America/Los_Angeles)) AS date_format(TIMESTAMP_NTZ 
'2023-08-18 09:13:14.123456', yyyy-MM-dd HH:mm:ss.SSSSSS)#x, 
date_format(cast(2023-08-18 09:13:14.123456 as timestamp), yyyy-MM-dd 
HH:mm:ss.SSSSSS, Some(America/Los_Angeles)) AS date_format(TIMESTAMP_NTZ 
'2023-08-18 09:13:14.123456', yyyy-MM-dd HH:mm:ss.SSSSSS)#x, 
date_format(cast(2023-08-18 09:13:14.123456 as timestamp), yyyy-MM-dd HH:mm 
[...]
 +- OneRowRelation
+
+
+-- !query
+select to_char(TIME'12:13:14', 'HH:mm:ss'), to_varchar(TIME'12:13:14', 
'HH:mm:ss')
+-- !query analysis
+Project [date_format(12:13:14, HH:mm:ss, Some(America/Los_Angeles)) AS 
date_format(TIME '12:13:14', HH:mm:ss)#x, date_format(12:13:14, HH:mm:ss, 
Some(America/Los_Angeles)) AS date_format(TIME '12:13:14', HH:mm:ss)#x]
++- OneRowRelation
+
+
+-- !query
+select to_char(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS'), 
to_varchar(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS')
+-- !query analysis
+Project [date_format(23:59:59.123456, HH:mm:ss.SSSSSS, 
Some(America/Los_Angeles)) AS date_format(TIME '23:59:59.123456', 
HH:mm:ss.SSSSSS)#x, date_format(23:59:59.123456, HH:mm:ss.SSSSSS, 
Some(America/Los_Angeles)) AS date_format(TIME '23:59:59.123456', 
HH:mm:ss.SSSSSS)#x]
++- OneRowRelation
diff --git 
a/sql/core/src/test/resources/sql-tests/analyzer-results/datetime-formatting.sql.out
 
b/sql/core/src/test/resources/sql-tests/analyzer-results/datetime-formatting.sql.out
index 7c5f1260b648..b61a35681b0a 100644
--- 
a/sql/core/src/test/resources/sql-tests/analyzer-results/datetime-formatting.sql.out
+++ 
b/sql/core/src/test/resources/sql-tests/analyzer-results/datetime-formatting.sql.out
@@ -393,3 +393,17 @@ select date_format(timestamp_ntz'2023-08-18 
09:13:14.123456', 'yyyy-MM-dd HH:mm:
 -- !query analysis
 Project [date_format(cast(2023-08-18 09:13:14.123456 as timestamp), yyyy-MM-dd 
HH:mm:ss.SSSSSS, Some(America/Los_Angeles)) AS date_format(TIMESTAMP_NTZ 
'2023-08-18 09:13:14.123456', yyyy-MM-dd HH:mm:ss.SSSSSS)#x, 
date_format(cast(2023-08-18 09:13:14.123456 as timestamp), yyyy-MM-dd 
HH:mm:ss.SSSSSS, Some(America/Los_Angeles)) AS date_format(TIMESTAMP_NTZ 
'2023-08-18 09:13:14.123456', yyyy-MM-dd HH:mm:ss.SSSSSS)#x, 
date_format(cast(2023-08-18 09:13:14.123456 as timestamp), yyyy-MM-dd HH:mm 
[...]
 +- OneRowRelation
+
+
+-- !query
+select to_char(TIME'12:13:14', 'HH:mm:ss'), to_varchar(TIME'12:13:14', 
'HH:mm:ss')
+-- !query analysis
+Project [date_format(12:13:14, HH:mm:ss, Some(America/Los_Angeles)) AS 
date_format(TIME '12:13:14', HH:mm:ss)#x, date_format(12:13:14, HH:mm:ss, 
Some(America/Los_Angeles)) AS date_format(TIME '12:13:14', HH:mm:ss)#x]
++- OneRowRelation
+
+
+-- !query
+select to_char(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS'), 
to_varchar(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS')
+-- !query analysis
+Project [date_format(23:59:59.123456, HH:mm:ss.SSSSSS, 
Some(America/Los_Angeles)) AS date_format(TIME '23:59:59.123456', 
HH:mm:ss.SSSSSS)#x, date_format(23:59:59.123456, HH:mm:ss.SSSSSS, 
Some(America/Los_Angeles)) AS date_format(TIME '23:59:59.123456', 
HH:mm:ss.SSSSSS)#x]
++- OneRowRelation
diff --git 
a/sql/core/src/test/resources/sql-tests/inputs/datetime-formatting.sql 
b/sql/core/src/test/resources/sql-tests/inputs/datetime-formatting.sql
index 3618bb5c399f..aefa8e8dd20f 100644
--- a/sql/core/src/test/resources/sql-tests/inputs/datetime-formatting.sql
+++ b/sql/core/src/test/resources/sql-tests/inputs/datetime-formatting.sql
@@ -71,3 +71,7 @@ select col, date_format(col, ''), to_char(col, ''), 
to_varchar(col, '') from v;
 select date_format(date'2023-08-18', 'yyyy-MM-dd'), to_char(date'2023-08-18', 
'yyyy-MM-dd'), to_varchar(date'2023-08-18', 'yyyy-MM-dd');
 select date_format(timestamp_ltz'2023-08-18 09:13:14.123456Z', 'yyyy-MM-dd 
HH:mm:ss.SSSSSSZ'), to_char(timestamp_ltz'2023-08-18 09:13:14.123456Z', 
'yyyy-MM-dd HH:mm:ss.SSSSSSZ'), to_varchar(timestamp_ltz'2023-08-18 
09:13:14.123456Z', 'yyyy-MM-dd HH:mm:ss.SSSSSSZ');
 select date_format(timestamp_ntz'2023-08-18 09:13:14.123456', 'yyyy-MM-dd 
HH:mm:ss.SSSSSS'), to_char(timestamp_ntz'2023-08-18 09:13:14.123456', 
'yyyy-MM-dd HH:mm:ss.SSSSSS'), to_varchar(timestamp_ntz'2023-08-18 
09:13:14.123456', 'yyyy-MM-dd HH:mm:ss.SSSSSS');
+
+-- SPARK-57575: TIME type formatting
+select to_char(TIME'12:13:14', 'HH:mm:ss'), to_varchar(TIME'12:13:14', 
'HH:mm:ss');
+select to_char(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS'), 
to_varchar(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS');
diff --git 
a/sql/core/src/test/resources/sql-tests/results/datetime-formatting-legacy.sql.out
 
b/sql/core/src/test/resources/sql-tests/results/datetime-formatting-legacy.sql.out
index ba0e9421e5b5..401aff976e9e 100644
--- 
a/sql/core/src/test/resources/sql-tests/results/datetime-formatting-legacy.sql.out
+++ 
b/sql/core/src/test/resources/sql-tests/results/datetime-formatting-legacy.sql.out
@@ -462,3 +462,19 @@ select date_format(timestamp_ntz'2023-08-18 
09:13:14.123456', 'yyyy-MM-dd HH:mm:
 struct<date_format(TIMESTAMP_NTZ '2023-08-18 09:13:14.123456', yyyy-MM-dd 
HH:mm:ss.SSSSSS):string,date_format(TIMESTAMP_NTZ '2023-08-18 09:13:14.123456', 
yyyy-MM-dd HH:mm:ss.SSSSSS):string,date_format(TIMESTAMP_NTZ '2023-08-18 
09:13:14.123456', yyyy-MM-dd HH:mm:ss.SSSSSS):string>
 -- !query output
 2023-08-18 09:13:14.000123     2023-08-18 09:13:14.000123      2023-08-18 
09:13:14.000123
+
+
+-- !query
+select to_char(TIME'12:13:14', 'HH:mm:ss'), to_varchar(TIME'12:13:14', 
'HH:mm:ss')
+-- !query schema
+struct<date_format(TIME '12:13:14', HH:mm:ss):string,date_format(TIME 
'12:13:14', HH:mm:ss):string>
+-- !query output
+12:13:14       12:13:14
+
+
+-- !query
+select to_char(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS'), 
to_varchar(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS')
+-- !query schema
+struct<date_format(TIME '23:59:59.123456', 
HH:mm:ss.SSSSSS):string,date_format(TIME '23:59:59.123456', 
HH:mm:ss.SSSSSS):string>
+-- !query output
+23:59:59.123456        23:59:59.123456
diff --git 
a/sql/core/src/test/resources/sql-tests/results/datetime-formatting.sql.out 
b/sql/core/src/test/resources/sql-tests/results/datetime-formatting.sql.out
index f659dbf0083d..76a02428056f 100644
--- a/sql/core/src/test/resources/sql-tests/results/datetime-formatting.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/datetime-formatting.sql.out
@@ -450,3 +450,19 @@ select date_format(timestamp_ntz'2023-08-18 
09:13:14.123456', 'yyyy-MM-dd HH:mm:
 struct<date_format(TIMESTAMP_NTZ '2023-08-18 09:13:14.123456', yyyy-MM-dd 
HH:mm:ss.SSSSSS):string,date_format(TIMESTAMP_NTZ '2023-08-18 09:13:14.123456', 
yyyy-MM-dd HH:mm:ss.SSSSSS):string,date_format(TIMESTAMP_NTZ '2023-08-18 
09:13:14.123456', yyyy-MM-dd HH:mm:ss.SSSSSS):string>
 -- !query output
 2023-08-18 09:13:14.123456     2023-08-18 09:13:14.123456      2023-08-18 
09:13:14.123456
+
+
+-- !query
+select to_char(TIME'12:13:14', 'HH:mm:ss'), to_varchar(TIME'12:13:14', 
'HH:mm:ss')
+-- !query schema
+struct<date_format(TIME '12:13:14', HH:mm:ss):string,date_format(TIME 
'12:13:14', HH:mm:ss):string>
+-- !query output
+12:13:14       12:13:14
+
+
+-- !query
+select to_char(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS'), 
to_varchar(TIME'23:59:59.123456', 'HH:mm:ss.SSSSSS')
+-- !query schema
+struct<date_format(TIME '23:59:59.123456', 
HH:mm:ss.SSSSSS):string,date_format(TIME '23:59:59.123456', 
HH:mm:ss.SSSSSS):string>
+-- !query output
+23:59:59.123456        23:59:59.123456


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to