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

wenchen 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 b03a86923c0d [SPARK-51555][SQL] Add the time_diff() function
b03a86923c0d is described below

commit b03a86923c0daf9574dd484b68d91ba3493df708
Author: Uros Bojanic <uros.boja...@databricks.com>
AuthorDate: Thu Jul 31 14:06:44 2025 +0800

    [SPARK-51555][SQL] Add the time_diff() function
    
    ### What changes were proposed in this pull request?
    Implement the `time_diff` function, which returns the difference between 
two times measured in units.
    
    Syntax
    ```
    time_diff(unit, start, end)
    
    unit
     { MICROSECOND |
       MILLISECOND |
       SECOND |
       MINUTE |
       HOUR }
    ```
    
    Arguments
    
    - `unit`: A unit of measure.
    - `start`: A starting TIME expression.
    - `end`: An ending TIME expression.
    
    Returns
    An INTEGER.
    If start is greater than end the result is negative.
    
    ### Why are the changes needed?
    Users will be able to calculate time difference in specified units.
    
    ### Does this PR introduce _any_ user-facing change?
    Yes, this PR introduces a new expression.
    
    ### How was this patch tested?
    New unit tests for time truncation, catalyst expression level unit tests 
with & without codegen, e2e SQL tests / golden files in both ANSI and non-ANSI 
modes.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    No.
    
    Closes #51715 from uros-db/timediff.
    
    Authored-by: Uros Bojanic <uros.boja...@databricks.com>
    Signed-off-by: Wenchen Fan <wenc...@databricks.com>
---
 .../src/main/resources/error/error-conditions.json |   2 +-
 .../sql/catalyst/analysis/FunctionRegistry.scala   |   1 +
 .../sql/catalyst/expressions/timeExpressions.scala |  68 ++-
 .../spark/sql/catalyst/util/DateTimeUtils.scala    |  39 +-
 .../spark/sql/errors/QueryExecutionErrors.scala    |   6 +-
 .../expressions/TimeExpressionsSuite.scala         |  49 +-
 .../sql/catalyst/util/DateTimeUtilsSuite.scala     |  56 ++
 .../sql-functions/sql-expression-schema.md         |   1 +
 .../sql-tests/analyzer-results/time.sql.out        | 519 ++++++++++++++++
 .../src/test/resources/sql-tests/inputs/time.sql   |  89 +++
 .../test/resources/sql-tests/results/time.sql.out  | 659 ++++++++++++++++++++-
 11 files changed, 1473 insertions(+), 16 deletions(-)

diff --git a/common/utils/src/main/resources/error/error-conditions.json 
b/common/utils/src/main/resources/error/error-conditions.json
index febc92eba902..e4482342d483 100644
--- a/common/utils/src/main/resources/error/error-conditions.json
+++ b/common/utils/src/main/resources/error/error-conditions.json
@@ -3436,7 +3436,7 @@
           "expects a string literal, but got <invalidValue>."
         ]
       },
-      "TIMETRUNC_UNIT" : {
+      "TIME_UNIT" : {
         "message" : [
           "expects one of the units 'HOUR', 'MINUTE', 'SECOND', 'MILLISECOND', 
'MICROSECOND', but got '<invalidValue>'."
         ]
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionRegistry.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionRegistry.scala
index 572165e87961..2cf85cb7e30c 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionRegistry.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionRegistry.scala
@@ -655,6 +655,7 @@ object FunctionRegistry {
     expressionBuilder("second", SecondExpressionBuilder),
     expression[ParseToTimestamp]("to_timestamp"),
     expression[ParseToDate]("to_date"),
+    expression[TimeDiff]("time_diff"),
     expression[ToTime]("to_time"),
     expression[ToBinary]("to_binary"),
     expression[ToUnixTimestamp]("to_unix_timestamp"),
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/timeExpressions.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/timeExpressions.scala
index 0f868f4e98dc..ff088876969b 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/timeExpressions.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/timeExpressions.scala
@@ -33,7 +33,7 @@ import org.apache.spark.sql.catalyst.util.TimeFormatter
 import org.apache.spark.sql.catalyst.util.TypeUtils.ordinalNumber
 import org.apache.spark.sql.errors.{QueryCompilationErrors, 
QueryExecutionErrors}
 import org.apache.spark.sql.internal.types.StringTypeWithCollation
-import org.apache.spark.sql.types.{AbstractDataType, AnyTimeType, ByteType, 
DataType, DayTimeIntervalType, DecimalType, IntegerType, ObjectType, TimeType}
+import org.apache.spark.sql.types.{AbstractDataType, AnyTimeType, ByteType, 
DataType, DayTimeIntervalType, DecimalType, IntegerType, LongType, ObjectType, 
TimeType}
 import org.apache.spark.sql.types.DayTimeIntervalType.{HOUR, SECOND}
 import org.apache.spark.unsafe.types.UTF8String
 
@@ -631,6 +631,72 @@ case class SubtractTimes(left: Expression, right: 
Expression)
     copy(left = newLeft, right = newRight)
 }
 
+/**
+ * Returns the difference between two times, measured in specified units.
+ */
+// scalastyle:off line.size.limit
+@ExpressionDescription(
+  usage = """
+    _FUNC_(unit, start, end) - Gets the difference between the times in the 
specified units.
+  """,
+  arguments = """
+    Arguments:
+      * unit - the unit of the difference between the given times
+          - "HOUR"
+          - "MINUTE"
+          - "SECOND"
+          - "MILLISECOND"
+          - "MICROSECOND"
+      * start - a starting TIME expression
+      * end - an ending TIME expression
+  """,
+  examples = """
+    Examples:
+      > SELECT _FUNC_('HOUR', TIME'20:30:29', TIME'21:30:28');
+       0
+      > SELECT _FUNC_('HOUR', TIME'20:30:29', TIME'21:30:29');
+       1
+      > SELECT _FUNC_('HOUR', TIME'20:30:29', TIME'12:00:00');
+       -8
+  """,
+  group = "datetime_funcs",
+  since = "4.1.0")
+// scalastyle:on line.size.limit
+case class TimeDiff(
+    unit: Expression,
+    start: Expression,
+    end: Expression)
+  extends TernaryExpression
+  with RuntimeReplaceable
+  with ImplicitCastInputTypes {
+
+  override def first: Expression = unit
+  override def second: Expression = start
+  override def third: Expression = end
+
+  override def inputTypes: Seq[AbstractDataType] =
+    Seq(StringTypeWithCollation(supportsTrimCollation = true), AnyTimeType, 
AnyTimeType)
+
+  override def dataType: DataType = LongType
+
+  override def prettyName: String = "time_diff"
+
+  override protected def withNewChildrenInternal(
+      newUnit: Expression, newStart: Expression, newEnd: Expression): TimeDiff 
= {
+    copy(unit = newUnit, start = newStart, end = newEnd)
+  }
+
+  override def replacement: Expression = {
+    StaticInvoke(
+      classOf[DateTimeUtils.type],
+      dataType,
+      "timeDiff",
+      Seq(unit, start, end),
+      Seq(unit.dataType, start.dataType, end.dataType)
+    )
+  }
+}
+
 // scalastyle:off line.size.limit
 @ExpressionDescription(
   usage = """
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
index 60a3285eb440..d63e3f91e898 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
@@ -520,7 +520,7 @@ object DateTimeUtils extends SparkDateTimeUtils {
       case "MILLISECOND" => ChronoUnit.MILLIS
       case "MICROSECOND" => ChronoUnit.MICROS
       case _ =>
-        throw QueryExecutionErrors.invalidTimeTruncUnitError("time_trunc", 
level.toString)
+        throw QueryExecutionErrors.invalidTimeUnitError("time_trunc", 
level.toString)
     }
   }
 
@@ -716,6 +716,43 @@ object DateTimeUtils extends SparkDateTimeUtils {
     (endNanos - startNanos) / NANOS_PER_MICROS
   }
 
+  // Helper method to get the number of nanoseconds per the given time unit, 
used for calculating
+  // the difference between two time values (timediff function). Supported 
units are: MICROSECOND,
+  // MILLISECOND, SECOND, MINUTE, HOUR.
+  private def getNanosPerTimeUnit(unit: UTF8String): Long = {
+    val unitStr = unit.toString
+    unitStr.toUpperCase(Locale.ROOT) match {
+      case "MICROSECOND" =>
+        NANOS_PER_MICROS
+      case "MILLISECOND" =>
+        NANOS_PER_MILLIS
+      case "SECOND" =>
+        NANOS_PER_SECOND
+      case "MINUTE" =>
+        NANOS_PER_SECOND * SECONDS_PER_MINUTE
+      case "HOUR" =>
+        NANOS_PER_SECOND * SECONDS_PER_MINUTE * MINUTES_PER_HOUR
+      case _ =>
+        throw QueryExecutionErrors.invalidTimeUnitError("timediff", unitStr)
+    }
+  }
+
+  /**
+   * Gets the difference between two time values in the specified unit.
+   *
+   * @param unit Specifies the interval units in which to express the 
difference between
+   *             the two time parameters. Supported units are: MICROSECOND, 
MILLISECOND,
+   *             SECOND, MINUTE, HOUR.
+   * @param startNanos A time value expressed as nanoseconds since the start 
of the day,
+   *                   which the function subtracts from `endNanos`.
+   * @param endNanos A time value expressed as nanoseconds since the start of 
the day,
+   *                 from which the function subtracts `startNanos`.
+   * @return The time span between two time values, in the units specified.
+   */
+  def timeDiff(unit: UTF8String, startNanos: Long, endNanos: Long): Long = {
+    (endNanos - startNanos) / getNanosPerTimeUnit(unit)
+  }
+
   /**
    * Subtracts two timestamps expressed as microseconds since 1970-01-01 
00:00:00Z, and returns
    * the difference in microseconds between local timestamps at the given time 
zone.
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
index a320bb334e3c..ba229a2e746c 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
@@ -3067,13 +3067,13 @@ private[sql] object QueryExecutionErrors extends 
QueryErrorsBase with ExecutionE
     )
   }
 
-  // Throws a SparkIllegalArgumentException when an invalid time truncation 
unit is specified.
+  // Throws a SparkIllegalArgumentException when an invalid time unit is 
specified.
   // Note that the supported units are: HOUR, MINUTE, SECOND, MILLISECOND, 
MICROSECOND.
-  def invalidTimeTruncUnitError(
+  def invalidTimeUnitError(
       functionName: String,
       invalidValue: String): Throwable = {
     new SparkIllegalArgumentException(
-      errorClass = "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+      errorClass = "INVALID_PARAMETER_VALUE.TIME_UNIT",
       messageParameters = Map(
         "functionName" -> toSQLId(functionName),
         "parameter" -> toSQLId("unit"),
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/TimeExpressionsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/TimeExpressionsSuite.scala
index 44dacccf1074..bccebf309b0c 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/TimeExpressionsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/TimeExpressionsSuite.scala
@@ -395,6 +395,53 @@ class TimeExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
       TimeType(), DayTimeIntervalType())
   }
 
+  test("SPARK-51555: Time difference") {
+    // Test cases for various difference units - from 09:32:05.359123 until 
17:23:49.906152.
+    val startTime: Long = localTime(9, 32, 5, 359123)
+    val startTimeLit: Expression = Literal(startTime, TimeType())
+    val endTime: Long = localTime(17, 23, 49, 906152)
+    val endTimeLit: Expression = Literal(endTime, TimeType())
+
+    // Test differences for valid units.
+    checkEvaluation(TimeDiff(Literal("HOUR"), startTimeLit, endTimeLit), 7L)
+    checkEvaluation(TimeDiff(Literal("MINUTE"), startTimeLit, endTimeLit), 
471L)
+    checkEvaluation(TimeDiff(Literal("SECOND"), startTimeLit, endTimeLit), 
28304L)
+    checkEvaluation(TimeDiff(Literal("MILLISECOND"), startTimeLit, 
endTimeLit), 28304547L)
+    checkEvaluation(TimeDiff(Literal("MICROSECOND"), startTimeLit, 
endTimeLit), 28304547029L)
+
+    // Test case-insensitive units.
+    checkEvaluation(TimeDiff(Literal("hour"), startTimeLit, endTimeLit), 7L)
+    checkEvaluation(TimeDiff(Literal("Minute"), startTimeLit, endTimeLit), 
471L)
+    checkEvaluation(TimeDiff(Literal("seconD"), startTimeLit, endTimeLit), 
28304L)
+    checkEvaluation(TimeDiff(Literal("milliSECOND"), startTimeLit, 
endTimeLit), 28304547L)
+    checkEvaluation(TimeDiff(Literal("mIcRoSeCoNd"), startTimeLit, 
endTimeLit), 28304547029L)
+
+    // Test invalid units.
+    val invalidUnits: Seq[String] = Seq("MS", "INVALID", "ABC", "XYZ", " ", "")
+    invalidUnits.foreach { unit =>
+      checkErrorInExpression[SparkIllegalArgumentException](
+        TimeDiff(Literal(unit), startTimeLit, endTimeLit),
+        condition = "INVALID_PARAMETER_VALUE.TIME_UNIT",
+        parameters = Map(
+          "functionName" -> "`timediff`",
+          "parameter" -> "`unit`",
+          "invalidValue" -> s"'$unit'"
+        )
+      )
+    }
+
+    // Test null inputs.
+    val nullUnit = Literal.create(null, StringType)
+    val nullTime = Literal.create(null, TimeType())
+    checkEvaluation(TimeDiff(nullUnit, startTimeLit, endTimeLit), null)
+    checkEvaluation(TimeDiff(Literal("hour"), nullTime, endTimeLit), null)
+    checkEvaluation(TimeDiff(Literal("hour"), startTimeLit, nullTime), null)
+    checkEvaluation(TimeDiff(nullUnit, nullTime, endTimeLit), null)
+    checkEvaluation(TimeDiff(nullUnit, startTimeLit, nullTime), null)
+    checkEvaluation(TimeDiff(Literal("hour"), nullTime, nullTime), null)
+    checkEvaluation(TimeDiff(nullUnit, nullTime, nullTime), null)
+  }
+
   test("Subtract times") {
     checkEvaluation(
       SubtractTimes(Literal.create(null, TimeType()), Literal(LocalTime.MIN)),
@@ -471,7 +518,7 @@ class TimeExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
         exception = intercept[SparkIllegalArgumentException] {
           TimeTrunc(Literal(unit), Literal(testTime, TimeType())).eval()
         },
-        condition = "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+        condition = "INVALID_PARAMETER_VALUE.TIME_UNIT",
         parameters = Map(
           "functionName" -> "`time_trunc`",
           "parameter" -> "`unit`",
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
index 5862d394653f..b5b69a834037 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
@@ -1451,6 +1451,62 @@ class DateTimeUtilsSuite extends SparkFunSuite with 
Matchers with SQLHelper {
     )
   }
 
+  // Helper methods to assert results of the timeDiff method and verify 
execution symmetry.
+  private def testTimeDiff(unit: String, start: Long, end: Long, expected: 
Long): Unit = {
+    val unitStr = UTF8String.fromString(unit)
+    assert(timeDiff(unitStr, start, end) === expected)
+    assert(timeDiff(unitStr, end, start) === -expected)
+  }
+
+  test("SPARK-51555: time difference calculation using timeDiff") {
+    // Helper variables to express various units of time in nanoseconds.
+    val zero = 0L
+    val nano = zero + 1
+    val micro = 1000 * nano
+    val milli = 1000 * micro
+    val sec = 1000 * milli
+    val min = 60 * sec
+    val hour = 60 * min
+    val day = 24 * hour
+    val maxTime = day - nano
+
+    // Tests that return the same results for all supported units.
+    val supportedUnits = Seq("HOUR", "MINUTE", "SECOND", "MILLISECOND", 
"MICROSECOND")
+    supportedUnits.foreach(unit => {
+      testTimeDiff(unit, zero, zero, 0)
+      testTimeDiff(unit, zero, nano, 0)
+      testTimeDiff(unit, zero, nano * 999, 0)
+      testTimeDiff(unit, nano, nano, 0)
+      testTimeDiff(unit, nano, nano * 999, 0)
+      testTimeDiff(unit, maxTime, maxTime, 0)
+      testTimeDiff(unit, maxTime, maxTime - 999, 0)
+    })
+
+    // Tests that return different results for various supported units.
+    testTimeDiff("HOUR", hour, hour, 0)
+    testTimeDiff("MINUTE", min, min, 0)
+    testTimeDiff("SECOND", sec, sec, 0)
+    testTimeDiff("MILLISECOND", milli, milli, 0)
+    testTimeDiff("MICROSECOND", micro, micro, 0)
+    testTimeDiff("HOUR", zero, hour, 1)
+    testTimeDiff("MINUTE", zero, min, 1)
+    testTimeDiff("SECOND", zero, sec, 1)
+    testTimeDiff("MILLISECOND", zero, milli, 1)
+    testTimeDiff("MICROSECOND", zero, micro, 1)
+    testTimeDiff("HOUR", zero, maxTime, 23)
+    testTimeDiff("MINUTE", zero, maxTime, 1439)
+    testTimeDiff("SECOND", zero, maxTime, 86399)
+    testTimeDiff("MILLISECOND", zero, maxTime, 86399999)
+    testTimeDiff("MICROSECOND", zero, maxTime, 86399999999L)
+    val start = 10 * hour + 53 * min + 45 * sec + 123 * milli + 456 * micro // 
10:53:45.123456
+    val end = 11 * hour + 54 * min + 46 * sec + 654 * milli + 321 * micro // 
11:54:46.654321
+    testTimeDiff("HOUR", start, end, 1)
+    testTimeDiff("MINUTE", start, end, 61)
+    testTimeDiff("SECOND", start, end, 3661)
+    testTimeDiff("MILLISECOND", start, end, 3661530)
+    testTimeDiff("MICROSECOND", start, end, 3661530865L)
+  }
+
   test("subtract times") {
       Seq(
         (LocalTime.MIDNIGHT, LocalTime.MIDNIGHT) -> 0,
diff --git a/sql/core/src/test/resources/sql-functions/sql-expression-schema.md 
b/sql/core/src/test/resources/sql-functions/sql-expression-schema.md
index 7b5c2c826470..6e6d520efbac 100644
--- a/sql/core/src/test/resources/sql-functions/sql-expression-schema.md
+++ b/sql/core/src/test/resources/sql-functions/sql-expression-schema.md
@@ -342,6 +342,7 @@
 | org.apache.spark.sql.catalyst.expressions.Subtract | - | SELECT 2 - 1 | 
struct<(2 - 1):int> |
 | org.apache.spark.sql.catalyst.expressions.Tan | tan | SELECT tan(0) | 
struct<TAN(0):double> |
 | org.apache.spark.sql.catalyst.expressions.Tanh | tanh | SELECT tanh(0) | 
struct<TANH(0):double> |
+| org.apache.spark.sql.catalyst.expressions.TimeDiff | time_diff | SELECT 
time_diff('HOUR', TIME'20:30:29', TIME'21:30:28') | struct<time_diff(HOUR, TIME 
'20:30:29', TIME '21:30:28'):bigint> |
 | org.apache.spark.sql.catalyst.expressions.TimeTrunc | time_trunc | SELECT 
time_trunc('HOUR', TIME'09:32:05.359') | struct<time_trunc(HOUR, TIME 
'09:32:05.359'):time(6)> |
 | org.apache.spark.sql.catalyst.expressions.TimeWindow | window | SELECT a, 
window.start, window.end, count(*) as cnt FROM VALUES ('A1', '2021-01-01 
00:00:00'), ('A1', '2021-01-01 00:04:30'), ('A1', '2021-01-01 00:06:00'), 
('A2', '2021-01-01 00:01:00') AS tab(a, b) GROUP by a, window(b, '5 minutes') 
ORDER BY a, start | struct<a:string,start:timestamp,end:timestamp,cnt:bigint> |
 | org.apache.spark.sql.catalyst.expressions.ToBinary | to_binary | SELECT 
to_binary('abc', 'utf-8') | struct<to_binary(abc, utf-8):binary> |
diff --git 
a/sql/core/src/test/resources/sql-tests/analyzer-results/time.sql.out 
b/sql/core/src/test/resources/sql-tests/analyzer-results/time.sql.out
index ffaead8ba78d..807087a92c02 100644
--- a/sql/core/src/test/resources/sql-tests/analyzer-results/time.sql.out
+++ b/sql/core/src/test/resources/sql-tests/analyzer-results/time.sql.out
@@ -1,4 +1,12 @@
 -- Automatically generated by SQLQueryTestSuite
+-- !query
+create temporary view timediff_view as select time'01:02:03' time_start, 
time'04:05:06' time_end, 'SECOND' unit
+-- !query analysis
+CreateViewCommand `timediff_view`, select time'01:02:03' time_start, 
time'04:05:06' time_end, 'SECOND' unit, false, false, LocalTempView, 
UNSUPPORTED, true
+   +- Project [01:02:03 AS time_start#x, 04:05:06 AS time_end#x, SECOND AS 
unit#x]
+      +- OneRowRelation
+
+
 -- !query
 create temporary view time_view as select '11:53:26.038344' time_str, 
'HH:mm:ss.SSSSSS' fmt_str
 -- !query analysis
@@ -990,6 +998,517 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
 }
 
 
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(HOUR, 00:00:00, 12:34:56) AS time_diff(HOUR, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(MINUTE, 00:00:00, 12:34:56) AS time_diff(MINUTE, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(SECOND, 00:00:00, 12:34:56) AS time_diff(SECOND, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(MILLISECOND, 00:00:00, 12:34:56) AS time_diff(MILLISECOND, 
TIME '00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(MICROSECOND, 00:00:00, 12:34:56) AS time_diff(MICROSECOND, 
TIME '00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('HOUR', time'01:02:03', time'12:34:56')
+-- !query analysis
+Project [time_diff(HOUR, 01:02:03, 12:34:56) AS time_diff(HOUR, TIME 
'01:02:03', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'01:02:03', time'12:34:56')
+-- !query analysis
+Project [time_diff(MINUTE, 01:02:03, 12:34:56) AS time_diff(MINUTE, TIME 
'01:02:03', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'01:02:03', time'12:34:56')
+-- !query analysis
+Project [time_diff(SECOND, 01:02:03, 12:34:56) AS time_diff(SECOND, TIME 
'01:02:03', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('HOUR', time'12:34:56', time'01:02:03')
+-- !query analysis
+Project [time_diff(HOUR, 12:34:56, 01:02:03) AS time_diff(HOUR, TIME 
'12:34:56', TIME '01:02:03')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'12:34:56', time'01:02:03')
+-- !query analysis
+Project [time_diff(MINUTE, 12:34:56, 01:02:03) AS time_diff(MINUTE, TIME 
'12:34:56', TIME '01:02:03')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'12:34:56', time'01:02:03')
+-- !query analysis
+Project [time_diff(SECOND, 12:34:56, 01:02:03) AS time_diff(SECOND, TIME 
'12:34:56', TIME '01:02:03')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.1')
+-- !query analysis
+Project [time_diff(HOUR, 00:00:00, 12:34:56.1) AS time_diff(HOUR, TIME 
'00:00:00', TIME '12:34:56.1')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.1')
+-- !query analysis
+Project [time_diff(MINUTE, 00:00:00, 12:34:56.1) AS time_diff(MINUTE, TIME 
'00:00:00', TIME '12:34:56.1')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.1')
+-- !query analysis
+Project [time_diff(SECOND, 00:00:00, 12:34:56.1) AS time_diff(SECOND, TIME 
'00:00:00', TIME '12:34:56.1')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.1')
+-- !query analysis
+Project [time_diff(MILLISECOND, 00:00:00, 12:34:56.1) AS 
time_diff(MILLISECOND, TIME '00:00:00', TIME '12:34:56.1')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.1')
+-- !query analysis
+Project [time_diff(MICROSECOND, 00:00:00, 12:34:56.1) AS 
time_diff(MICROSECOND, TIME '00:00:00', TIME '12:34:56.1')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.123456')
+-- !query analysis
+Project [time_diff(HOUR, 00:00:00, 12:34:56.123456) AS time_diff(HOUR, TIME 
'00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.123456')
+-- !query analysis
+Project [time_diff(MINUTE, 00:00:00, 12:34:56.123456) AS time_diff(MINUTE, 
TIME '00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.123456')
+-- !query analysis
+Project [time_diff(SECOND, 00:00:00, 12:34:56.123456) AS time_diff(SECOND, 
TIME '00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.123456')
+-- !query analysis
+Project [time_diff(MILLISECOND, 00:00:00, 12:34:56.123456) AS 
time_diff(MILLISECOND, TIME '00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.123456')
+-- !query analysis
+Project [time_diff(MICROSECOND, 00:00:00, 12:34:56.123456) AS 
time_diff(MICROSECOND, TIME '00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.123456789')
+-- !query analysis
+Project [time_diff(HOUR, 00:00:00, 12:34:56.123456) AS time_diff(HOUR, TIME 
'00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.123456789')
+-- !query analysis
+Project [time_diff(MINUTE, 00:00:00, 12:34:56.123456) AS time_diff(MINUTE, 
TIME '00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.123456789')
+-- !query analysis
+Project [time_diff(SECOND, 00:00:00, 12:34:56.123456) AS time_diff(SECOND, 
TIME '00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.123456789')
+-- !query analysis
+Project [time_diff(MILLISECOND, 00:00:00, 12:34:56.123456) AS 
time_diff(MILLISECOND, TIME '00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.123456789')
+-- !query analysis
+Project [time_diff(MICROSECOND, 00:00:00, 12:34:56.123456) AS 
time_diff(MICROSECOND, TIME '00:00:00', TIME '12:34:56.123456')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('hour', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(hour, 00:00:00, 12:34:56) AS time_diff(hour, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MiNuTe', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(MiNuTe, 00:00:00, 12:34:56) AS time_diff(MiNuTe, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('sEcOnD', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(sEcOnD, 00:00:00, 12:34:56) AS time_diff(sEcOnD, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('Millisecond', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(Millisecond, 00:00:00, 12:34:56) AS time_diff(Millisecond, 
TIME '00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('microseconD', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(microseconD, 00:00:00, 12:34:56) AS time_diff(microseconD, 
TIME '00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'00:00:00')
+-- !query analysis
+Project [time_diff(HOUR, 00:00:00, 00:00:00) AS time_diff(HOUR, TIME 
'00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'00:00:00')
+-- !query analysis
+Project [time_diff(MINUTE, 00:00:00, 00:00:00) AS time_diff(MINUTE, TIME 
'00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'00:00:00')
+-- !query analysis
+Project [time_diff(SECOND, 00:00:00, 00:00:00) AS time_diff(SECOND, TIME 
'00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'00:00:00')
+-- !query analysis
+Project [time_diff(MILLISECOND, 00:00:00, 00:00:00) AS time_diff(MILLISECOND, 
TIME '00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'00:00:00')
+-- !query analysis
+Project [time_diff(MICROSECOND, 00:00:00, 00:00:00) AS time_diff(MICROSECOND, 
TIME '00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'00:00:00.000000001')
+-- !query analysis
+Project [time_diff(HOUR, 00:00:00, 00:00:00) AS time_diff(HOUR, TIME 
'00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'00:00:00.000000001')
+-- !query analysis
+Project [time_diff(MINUTE, 00:00:00, 00:00:00) AS time_diff(MINUTE, TIME 
'00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'00:00:00.000000001')
+-- !query analysis
+Project [time_diff(SECOND, 00:00:00, 00:00:00) AS time_diff(SECOND, TIME 
'00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'00:00:00.000000001')
+-- !query analysis
+Project [time_diff(MILLISECOND, 00:00:00, 00:00:00) AS time_diff(MILLISECOND, 
TIME '00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'00:00:00.000000001')
+-- !query analysis
+Project [time_diff(MICROSECOND, 00:00:00, 00:00:00) AS time_diff(MICROSECOND, 
TIME '00:00:00', TIME '00:00:00')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'23:59:59.999999999')
+-- !query analysis
+Project [time_diff(HOUR, 00:00:00, 23:59:59.999999) AS time_diff(HOUR, TIME 
'00:00:00', TIME '23:59:59.999999')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'23:59:59.999999999')
+-- !query analysis
+Project [time_diff(MINUTE, 00:00:00, 23:59:59.999999) AS time_diff(MINUTE, 
TIME '00:00:00', TIME '23:59:59.999999')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'23:59:59.999999999')
+-- !query analysis
+Project [time_diff(SECOND, 00:00:00, 23:59:59.999999) AS time_diff(SECOND, 
TIME '00:00:00', TIME '23:59:59.999999')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'23:59:59.999999999')
+-- !query analysis
+Project [time_diff(MILLISECOND, 00:00:00, 23:59:59.999999) AS 
time_diff(MILLISECOND, TIME '00:00:00', TIME '23:59:59.999999')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'23:59:59.999999999')
+-- !query analysis
+Project [time_diff(MICROSECOND, 00:00:00, 23:59:59.999999) AS 
time_diff(MICROSECOND, TIME '00:00:00', TIME '23:59:59.999999')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(, 00:00:00, 12:34:56) AS time_diff(, TIME '00:00:00', TIME 
'12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff(' ', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff( , 00:00:00, 12:34:56) AS time_diff( , TIME '00:00:00', 
TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MS', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(MS, 00:00:00, 12:34:56) AS time_diff(MS, TIME '00:00:00', 
TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('DAY', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(DAY, 00:00:00, 12:34:56) AS time_diff(DAY, TIME '00:00:00', 
TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('WEEK', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(WEEK, 00:00:00, 12:34:56) AS time_diff(WEEK, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('ABCD', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(ABCD, 00:00:00, 12:34:56) AS time_diff(ABCD, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('QUARTER', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(QUARTER, 00:00:00, 12:34:56) AS time_diff(QUARTER, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('INVALID', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(INVALID, 00:00:00, 12:34:56) AS time_diff(INVALID, TIME 
'00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('INVALID_UNIT', time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(INVALID_UNIT, 00:00:00, 12:34:56) AS 
time_diff(INVALID_UNIT, TIME '00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff(NULL, time'00:00:00', time'12:34:56')
+-- !query analysis
+Project [time_diff(cast(null as string), 00:00:00, 12:34:56) AS 
time_diff(NULL, TIME '00:00:00', TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', NULL, time'12:34:56')
+-- !query analysis
+Project [time_diff(MICROSECOND, cast(null as time(6)), 12:34:56) AS 
time_diff(MICROSECOND, NULL, TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', NULL)
+-- !query analysis
+Project [time_diff(MICROSECOND, 00:00:00, cast(null as time(6))) AS 
time_diff(MICROSECOND, TIME '00:00:00', NULL)#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff(NULL, NULL, time'12:34:56')
+-- !query analysis
+Project [time_diff(cast(null as string), cast(null as time(6)), 12:34:56) AS 
time_diff(NULL, NULL, TIME '12:34:56')#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff(NULL, time'00:00:00', NULL)
+-- !query analysis
+Project [time_diff(cast(null as string), 00:00:00, cast(null as time(6))) AS 
time_diff(NULL, TIME '00:00:00', NULL)#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('MICROSECOND', NULL, NULL)
+-- !query analysis
+Project [time_diff(MICROSECOND, cast(null as time(6)), cast(null as time(6))) 
AS time_diff(MICROSECOND, NULL, NULL)#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff(NULL, NULL, NULL)
+-- !query analysis
+Project [time_diff(cast(null as string), cast(null as time(6)), cast(null as 
time(6))) AS time_diff(NULL, NULL, NULL)#xL]
++- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time_start, time_end) FROM timediff_view
+-- !query analysis
+Project [time_diff(SECOND, time_start#x, time_end#x) AS time_diff(SECOND, 
time_start, time_end)#xL]
++- SubqueryAlias timediff_view
+   +- View (`timediff_view`, [time_start#x, time_end#x, unit#x])
+      +- Project [cast(time_start#x as time(6)) AS time_start#x, 
cast(time_end#x as time(6)) AS time_end#x, cast(unit#x as string) AS unit#x]
+         +- Project [01:02:03 AS time_start#x, 04:05:06 AS time_end#x, SECOND 
AS unit#x]
+            +- OneRowRelation
+
+
+-- !query
+SELECT time_diff(unit, time'01:02:03', time_end) FROM timediff_view
+-- !query analysis
+Project [time_diff(unit#x, 01:02:03, time_end#x) AS time_diff(unit, TIME 
'01:02:03', time_end)#xL]
++- SubqueryAlias timediff_view
+   +- View (`timediff_view`, [time_start#x, time_end#x, unit#x])
+      +- Project [cast(time_start#x as time(6)) AS time_start#x, 
cast(time_end#x as time(6)) AS time_end#x, cast(unit#x as string) AS unit#x]
+         +- Project [01:02:03 AS time_start#x, 04:05:06 AS time_end#x, SECOND 
AS unit#x]
+            +- OneRowRelation
+
+
+-- !query
+SELECT time_diff(unit, time_start, time'04:05:06') FROM timediff_view
+-- !query analysis
+Project [time_diff(unit#x, time_start#x, 04:05:06) AS time_diff(unit, 
time_start, TIME '04:05:06')#xL]
++- SubqueryAlias timediff_view
+   +- View (`timediff_view`, [time_start#x, time_end#x, unit#x])
+      +- Project [cast(time_start#x as time(6)) AS time_start#x, 
cast(time_end#x as time(6)) AS time_end#x, cast(unit#x as string) AS unit#x]
+         +- Project [01:02:03 AS time_start#x, 04:05:06 AS time_end#x, SECOND 
AS unit#x]
+            +- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time'01:02:03', time_end) FROM timediff_view
+-- !query analysis
+Project [time_diff(SECOND, 01:02:03, time_end#x) AS time_diff(SECOND, TIME 
'01:02:03', time_end)#xL]
++- SubqueryAlias timediff_view
+   +- View (`timediff_view`, [time_start#x, time_end#x, unit#x])
+      +- Project [cast(time_start#x as time(6)) AS time_start#x, 
cast(time_end#x as time(6)) AS time_end#x, cast(unit#x as string) AS unit#x]
+         +- Project [01:02:03 AS time_start#x, 04:05:06 AS time_end#x, SECOND 
AS unit#x]
+            +- OneRowRelation
+
+
+-- !query
+SELECT time_diff('SECOND', time_start, time'04:05:06') FROM timediff_view
+-- !query analysis
+Project [time_diff(SECOND, time_start#x, 04:05:06) AS time_diff(SECOND, 
time_start, TIME '04:05:06')#xL]
++- SubqueryAlias timediff_view
+   +- View (`timediff_view`, [time_start#x, time_end#x, unit#x])
+      +- Project [cast(time_start#x as time(6)) AS time_start#x, 
cast(time_end#x as time(6)) AS time_end#x, cast(unit#x as string) AS unit#x]
+         +- Project [01:02:03 AS time_start#x, 04:05:06 AS time_end#x, SECOND 
AS unit#x]
+            +- OneRowRelation
+
+
+-- !query
+SELECT time_diff(unit, time'01:02:03', time'04:05:06') FROM timediff_view
+-- !query analysis
+Project [time_diff(unit#x, 01:02:03, 04:05:06) AS time_diff(unit, TIME 
'01:02:03', TIME '04:05:06')#xL]
++- SubqueryAlias timediff_view
+   +- View (`timediff_view`, [time_start#x, time_end#x, unit#x])
+      +- Project [cast(time_start#x as time(6)) AS time_start#x, 
cast(time_end#x as time(6)) AS time_end#x, cast(unit#x as string) AS unit#x]
+         +- Project [01:02:03 AS time_start#x, 04:05:06 AS time_end#x, SECOND 
AS unit#x]
+            +- OneRowRelation
+
+
+-- !query
+SELECT time_diff(unit, time_start, time_end) FROM timediff_view
+-- !query analysis
+Project [time_diff(unit#x, time_start#x, time_end#x) AS time_diff(unit, 
time_start, time_end)#xL]
++- SubqueryAlias timediff_view
+   +- View (`timediff_view`, [time_start#x, time_end#x, unit#x])
+      +- Project [cast(time_start#x as time(6)) AS time_start#x, 
cast(time_end#x as time(6)) AS time_end#x, cast(unit#x as string) AS unit#x]
+         +- Project [01:02:03 AS time_start#x, 04:05:06 AS time_end#x, SECOND 
AS unit#x]
+            +- OneRowRelation
+
+
 -- !query
 SELECT TIME'12:30:41' - TIME'10:00'
 -- !query analysis
diff --git a/sql/core/src/test/resources/sql-tests/inputs/time.sql 
b/sql/core/src/test/resources/sql-tests/inputs/time.sql
index 44d44e2b4a42..0c9eda1eb4af 100644
--- a/sql/core/src/test/resources/sql-tests/inputs/time.sql
+++ b/sql/core/src/test/resources/sql-tests/inputs/time.sql
@@ -1,5 +1,7 @@
 -- time literals, functions and operations
 
+create temporary view timediff_view as select time'01:02:03' time_start, 
time'04:05:06' time_end, 'SECOND' unit;
+
 create temporary view time_view as select '11:53:26.038344' time_str, 
'HH:mm:ss.SSSSSS' fmt_str;
 
 create temporary view trunc_time_view as select time'11:53:26.038344' 
time_val, 'MINUTE' unit;
@@ -171,6 +173,93 @@ SELECT '00:00:00.0001' :: TIME(4) - INTERVAL '0 
00:00:00.0001' DAY TO SECOND;
 SELECT '08:30' :: TIME(0) - INTERVAL '6' HOUR;
 SELECT '10:00:01' :: TIME(1) - INTERVAL '1' MONTH;
 
+-- SPARK-51555: time difference.
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56');
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56');
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56');
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56');
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56');
+
+-- SPARK-51555: positive and negative time difference.
+SELECT time_diff('HOUR', time'01:02:03', time'12:34:56');
+SELECT time_diff('MINUTE', time'01:02:03', time'12:34:56');
+SELECT time_diff('SECOND', time'01:02:03', time'12:34:56');
+SELECT time_diff('HOUR', time'12:34:56', time'01:02:03');
+SELECT time_diff('MINUTE', time'12:34:56', time'01:02:03');
+SELECT time_diff('SECOND', time'12:34:56', time'01:02:03');
+
+-- SPARK-51555: time difference with various time precisions.
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.1');
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.1');
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.1');
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.1');
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.1');
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.123456');
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.123456');
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.123456');
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.123456');
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.123456');
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.123456789');
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.123456789');
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.123456789');
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.123456789');
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.123456789');
+
+-- SPARK-51555: time difference with various unit cases.
+SELECT time_diff('hour', time'00:00:00', time'12:34:56');
+SELECT time_diff('MiNuTe', time'00:00:00', time'12:34:56');
+SELECT time_diff('sEcOnD', time'00:00:00', time'12:34:56');
+SELECT time_diff('Millisecond', time'00:00:00', time'12:34:56');
+SELECT time_diff('microseconD', time'00:00:00', time'12:34:56');
+
+-- SPARK-51555: time difference with zero time.
+SELECT time_diff('HOUR', time'00:00:00', time'00:00:00');
+SELECT time_diff('MINUTE', time'00:00:00', time'00:00:00');
+SELECT time_diff('SECOND', time'00:00:00', time'00:00:00');
+SELECT time_diff('MILLISECOND', time'00:00:00', time'00:00:00');
+SELECT time_diff('MICROSECOND', time'00:00:00', time'00:00:00');
+-- SPARK-51555: time difference with small time.
+SELECT time_diff('HOUR', time'00:00:00', time'00:00:00.000000001');
+SELECT time_diff('MINUTE', time'00:00:00', time'00:00:00.000000001');
+SELECT time_diff('SECOND', time'00:00:00', time'00:00:00.000000001');
+SELECT time_diff('MILLISECOND', time'00:00:00', time'00:00:00.000000001');
+SELECT time_diff('MICROSECOND', time'00:00:00', time'00:00:00.000000001');
+-- SPARK-51555: time difference with max time.
+SELECT time_diff('HOUR', time'00:00:00', time'23:59:59.999999999');
+SELECT time_diff('MINUTE', time'00:00:00', time'23:59:59.999999999');
+SELECT time_diff('SECOND', time'00:00:00', time'23:59:59.999999999');
+SELECT time_diff('MILLISECOND', time'00:00:00', time'23:59:59.999999999');
+SELECT time_diff('MICROSECOND', time'00:00:00', time'23:59:59.999999999');
+
+-- SPARK-51555: time difference with invalid unit.
+SELECT time_diff('', time'00:00:00', time'12:34:56');
+SELECT time_diff(' ', time'00:00:00', time'12:34:56');
+SELECT time_diff('MS', time'00:00:00', time'12:34:56');
+SELECT time_diff('DAY', time'00:00:00', time'12:34:56');
+SELECT time_diff('WEEK', time'00:00:00', time'12:34:56');
+SELECT time_diff('ABCD', time'00:00:00', time'12:34:56');
+SELECT time_diff('QUARTER', time'00:00:00', time'12:34:56');
+SELECT time_diff('INVALID', time'00:00:00', time'12:34:56');
+SELECT time_diff('INVALID_UNIT', time'00:00:00', time'12:34:56');
+
+-- SPARK-51555: time difference with null inputs.
+SELECT time_diff(NULL, time'00:00:00', time'12:34:56');
+SELECT time_diff('MICROSECOND', NULL, time'12:34:56');
+SELECT time_diff('MICROSECOND', time'00:00:00', NULL);
+SELECT time_diff(NULL, NULL, time'12:34:56');
+SELECT time_diff(NULL, time'00:00:00', NULL);
+SELECT time_diff('MICROSECOND', NULL, NULL);
+SELECT time_diff(NULL, NULL, NULL);
+
+-- SPARK-51555: time difference with table columns.
+SELECT time_diff('SECOND', time_start, time_end) FROM timediff_view;
+SELECT time_diff(unit, time'01:02:03', time_end) FROM timediff_view;
+SELECT time_diff(unit, time_start, time'04:05:06') FROM timediff_view;
+SELECT time_diff('SECOND', time'01:02:03', time_end) FROM timediff_view;
+SELECT time_diff('SECOND', time_start, time'04:05:06') FROM timediff_view;
+SELECT time_diff(unit, time'01:02:03', time'04:05:06') FROM timediff_view;
+SELECT time_diff(unit, time_start, time_end) FROM timediff_view;
+
 -- Subtract times
 SELECT TIME'12:30:41' - TIME'10:00';
 SELECT TIME'08:30' - NULL;
diff --git a/sql/core/src/test/resources/sql-tests/results/time.sql.out 
b/sql/core/src/test/resources/sql-tests/results/time.sql.out
index bad832c0c726..27e869d9e5c7 100644
--- a/sql/core/src/test/resources/sql-tests/results/time.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/time.sql.out
@@ -1,4 +1,12 @@
 -- Automatically generated by SQLQueryTestSuite
+-- !query
+create temporary view timediff_view as select time'01:02:03' time_start, 
time'04:05:06' time_end, 'SECOND' unit
+-- !query schema
+struct<>
+-- !query output
+
+
+
 -- !query
 create temporary view time_view as select '11:53:26.038344' time_str, 
'HH:mm:ss.SSSSSS' fmt_str
 -- !query schema
@@ -891,7 +899,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -908,7 +916,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -925,7 +933,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -942,7 +950,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -959,7 +967,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -976,7 +984,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -993,7 +1001,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -1010,7 +1018,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -1027,7 +1035,7 @@ struct<>
 -- !query output
 org.apache.spark.SparkIllegalArgumentException
 {
-  "errorClass" : "INVALID_PARAMETER_VALUE.TIMETRUNC_UNIT",
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
   "sqlState" : "22023",
   "messageParameters" : {
     "functionName" : "`time_trunc`",
@@ -1237,6 +1245,639 @@ org.apache.spark.sql.catalyst.ExtendedAnalysisException
 }
 
 
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(HOUR, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+12
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(MINUTE, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+754
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(SECOND, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+45296
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(MILLISECOND, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+45296000
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(MICROSECOND, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+45296000000
+
+
+-- !query
+SELECT time_diff('HOUR', time'01:02:03', time'12:34:56')
+-- !query schema
+struct<time_diff(HOUR, TIME '01:02:03', TIME '12:34:56'):bigint>
+-- !query output
+11
+
+
+-- !query
+SELECT time_diff('MINUTE', time'01:02:03', time'12:34:56')
+-- !query schema
+struct<time_diff(MINUTE, TIME '01:02:03', TIME '12:34:56'):bigint>
+-- !query output
+692
+
+
+-- !query
+SELECT time_diff('SECOND', time'01:02:03', time'12:34:56')
+-- !query schema
+struct<time_diff(SECOND, TIME '01:02:03', TIME '12:34:56'):bigint>
+-- !query output
+41573
+
+
+-- !query
+SELECT time_diff('HOUR', time'12:34:56', time'01:02:03')
+-- !query schema
+struct<time_diff(HOUR, TIME '12:34:56', TIME '01:02:03'):bigint>
+-- !query output
+-11
+
+
+-- !query
+SELECT time_diff('MINUTE', time'12:34:56', time'01:02:03')
+-- !query schema
+struct<time_diff(MINUTE, TIME '12:34:56', TIME '01:02:03'):bigint>
+-- !query output
+-692
+
+
+-- !query
+SELECT time_diff('SECOND', time'12:34:56', time'01:02:03')
+-- !query schema
+struct<time_diff(SECOND, TIME '12:34:56', TIME '01:02:03'):bigint>
+-- !query output
+-41573
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.1')
+-- !query schema
+struct<time_diff(HOUR, TIME '00:00:00', TIME '12:34:56.1'):bigint>
+-- !query output
+12
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.1')
+-- !query schema
+struct<time_diff(MINUTE, TIME '00:00:00', TIME '12:34:56.1'):bigint>
+-- !query output
+754
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.1')
+-- !query schema
+struct<time_diff(SECOND, TIME '00:00:00', TIME '12:34:56.1'):bigint>
+-- !query output
+45296
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.1')
+-- !query schema
+struct<time_diff(MILLISECOND, TIME '00:00:00', TIME '12:34:56.1'):bigint>
+-- !query output
+45296100
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.1')
+-- !query schema
+struct<time_diff(MICROSECOND, TIME '00:00:00', TIME '12:34:56.1'):bigint>
+-- !query output
+45296100000
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.123456')
+-- !query schema
+struct<time_diff(HOUR, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+12
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.123456')
+-- !query schema
+struct<time_diff(MINUTE, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+754
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.123456')
+-- !query schema
+struct<time_diff(SECOND, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+45296
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.123456')
+-- !query schema
+struct<time_diff(MILLISECOND, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+45296123
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.123456')
+-- !query schema
+struct<time_diff(MICROSECOND, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+45296123456
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'12:34:56.123456789')
+-- !query schema
+struct<time_diff(HOUR, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+12
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'12:34:56.123456789')
+-- !query schema
+struct<time_diff(MINUTE, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+754
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'12:34:56.123456789')
+-- !query schema
+struct<time_diff(SECOND, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+45296
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'12:34:56.123456789')
+-- !query schema
+struct<time_diff(MILLISECOND, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+45296123
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'12:34:56.123456789')
+-- !query schema
+struct<time_diff(MICROSECOND, TIME '00:00:00', TIME '12:34:56.123456'):bigint>
+-- !query output
+45296123456
+
+
+-- !query
+SELECT time_diff('hour', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(hour, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+12
+
+
+-- !query
+SELECT time_diff('MiNuTe', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(MiNuTe, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+754
+
+
+-- !query
+SELECT time_diff('sEcOnD', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(sEcOnD, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+45296
+
+
+-- !query
+SELECT time_diff('Millisecond', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(Millisecond, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+45296000
+
+
+-- !query
+SELECT time_diff('microseconD', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(microseconD, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+45296000000
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'00:00:00')
+-- !query schema
+struct<time_diff(HOUR, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'00:00:00')
+-- !query schema
+struct<time_diff(MINUTE, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'00:00:00')
+-- !query schema
+struct<time_diff(SECOND, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'00:00:00')
+-- !query schema
+struct<time_diff(MILLISECOND, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'00:00:00')
+-- !query schema
+struct<time_diff(MICROSECOND, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'00:00:00.000000001')
+-- !query schema
+struct<time_diff(HOUR, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'00:00:00.000000001')
+-- !query schema
+struct<time_diff(MINUTE, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'00:00:00.000000001')
+-- !query schema
+struct<time_diff(SECOND, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'00:00:00.000000001')
+-- !query schema
+struct<time_diff(MILLISECOND, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'00:00:00.000000001')
+-- !query schema
+struct<time_diff(MICROSECOND, TIME '00:00:00', TIME '00:00:00'):bigint>
+-- !query output
+0
+
+
+-- !query
+SELECT time_diff('HOUR', time'00:00:00', time'23:59:59.999999999')
+-- !query schema
+struct<time_diff(HOUR, TIME '00:00:00', TIME '23:59:59.999999'):bigint>
+-- !query output
+23
+
+
+-- !query
+SELECT time_diff('MINUTE', time'00:00:00', time'23:59:59.999999999')
+-- !query schema
+struct<time_diff(MINUTE, TIME '00:00:00', TIME '23:59:59.999999'):bigint>
+-- !query output
+1439
+
+
+-- !query
+SELECT time_diff('SECOND', time'00:00:00', time'23:59:59.999999999')
+-- !query schema
+struct<time_diff(SECOND, TIME '00:00:00', TIME '23:59:59.999999'):bigint>
+-- !query output
+86399
+
+
+-- !query
+SELECT time_diff('MILLISECOND', time'00:00:00', time'23:59:59.999999999')
+-- !query schema
+struct<time_diff(MILLISECOND, TIME '00:00:00', TIME '23:59:59.999999'):bigint>
+-- !query output
+86399999
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', time'23:59:59.999999999')
+-- !query schema
+struct<time_diff(MICROSECOND, TIME '00:00:00', TIME '23:59:59.999999'):bigint>
+-- !query output
+86399999999
+
+
+-- !query
+SELECT time_diff('', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "''",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff(' ', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "' '",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff('MS', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "'MS'",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff('DAY', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "'DAY'",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff('WEEK', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "'WEEK'",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff('ABCD', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "'ABCD'",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff('QUARTER', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "'QUARTER'",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff('INVALID', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "'INVALID'",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff('INVALID_UNIT', time'00:00:00', time'12:34:56')
+-- !query schema
+struct<>
+-- !query output
+org.apache.spark.SparkIllegalArgumentException
+{
+  "errorClass" : "INVALID_PARAMETER_VALUE.TIME_UNIT",
+  "sqlState" : "22023",
+  "messageParameters" : {
+    "functionName" : "`timediff`",
+    "invalidValue" : "'INVALID_UNIT'",
+    "parameter" : "`unit`"
+  }
+}
+
+
+-- !query
+SELECT time_diff(NULL, time'00:00:00', time'12:34:56')
+-- !query schema
+struct<time_diff(NULL, TIME '00:00:00', TIME '12:34:56'):bigint>
+-- !query output
+NULL
+
+
+-- !query
+SELECT time_diff('MICROSECOND', NULL, time'12:34:56')
+-- !query schema
+struct<time_diff(MICROSECOND, NULL, TIME '12:34:56'):bigint>
+-- !query output
+NULL
+
+
+-- !query
+SELECT time_diff('MICROSECOND', time'00:00:00', NULL)
+-- !query schema
+struct<time_diff(MICROSECOND, TIME '00:00:00', NULL):bigint>
+-- !query output
+NULL
+
+
+-- !query
+SELECT time_diff(NULL, NULL, time'12:34:56')
+-- !query schema
+struct<time_diff(NULL, NULL, TIME '12:34:56'):bigint>
+-- !query output
+NULL
+
+
+-- !query
+SELECT time_diff(NULL, time'00:00:00', NULL)
+-- !query schema
+struct<time_diff(NULL, TIME '00:00:00', NULL):bigint>
+-- !query output
+NULL
+
+
+-- !query
+SELECT time_diff('MICROSECOND', NULL, NULL)
+-- !query schema
+struct<time_diff(MICROSECOND, NULL, NULL):bigint>
+-- !query output
+NULL
+
+
+-- !query
+SELECT time_diff(NULL, NULL, NULL)
+-- !query schema
+struct<time_diff(NULL, NULL, NULL):bigint>
+-- !query output
+NULL
+
+
+-- !query
+SELECT time_diff('SECOND', time_start, time_end) FROM timediff_view
+-- !query schema
+struct<time_diff(SECOND, time_start, time_end):bigint>
+-- !query output
+10983
+
+
+-- !query
+SELECT time_diff(unit, time'01:02:03', time_end) FROM timediff_view
+-- !query schema
+struct<time_diff(unit, TIME '01:02:03', time_end):bigint>
+-- !query output
+10983
+
+
+-- !query
+SELECT time_diff(unit, time_start, time'04:05:06') FROM timediff_view
+-- !query schema
+struct<time_diff(unit, time_start, TIME '04:05:06'):bigint>
+-- !query output
+10983
+
+
+-- !query
+SELECT time_diff('SECOND', time'01:02:03', time_end) FROM timediff_view
+-- !query schema
+struct<time_diff(SECOND, TIME '01:02:03', time_end):bigint>
+-- !query output
+10983
+
+
+-- !query
+SELECT time_diff('SECOND', time_start, time'04:05:06') FROM timediff_view
+-- !query schema
+struct<time_diff(SECOND, time_start, TIME '04:05:06'):bigint>
+-- !query output
+10983
+
+
+-- !query
+SELECT time_diff(unit, time'01:02:03', time'04:05:06') FROM timediff_view
+-- !query schema
+struct<time_diff(unit, TIME '01:02:03', TIME '04:05:06'):bigint>
+-- !query output
+10983
+
+
+-- !query
+SELECT time_diff(unit, time_start, time_end) FROM timediff_view
+-- !query schema
+struct<time_diff(unit, time_start, time_end):bigint>
+-- !query output
+10983
+
+
 -- !query
 SELECT TIME'12:30:41' - TIME'10:00'
 -- !query schema


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@spark.apache.org
For additional commands, e-mail: commits-h...@spark.apache.org

Reply via email to