diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala index 2ed0e40a4c03f..17118499d0c87 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala @@ -102,7 +102,10 @@ case class Cast(child: Expression, dataType: DataType) extends UnaryExpression { // Timestamp to long, converting milliseconds to seconds private def timestampToLong(ts: Timestamp) = ts.getTime / 1000 - private def timestampToDouble(ts: Timestamp) = ts.getTime.toDouble / 1000 + private def timestampToDouble(ts: Timestamp) = { + // First part is the seconds since the beginning of time, followed by nanosecs. + ts.getTime / 1000 + ts.getNanos.toDouble / 1000000000 + } def castToLong: Any => Any = child.dataType match { case StringType => nullOrCast[String](_, s => try s.toLong catch { diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ExpressionEvaluationSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ExpressionEvaluationSuite.scala index 510b9e8bcec87..a897040b439e8 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ExpressionEvaluationSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ExpressionEvaluationSuite.scala @@ -245,14 +245,14 @@ class ExpressionEvaluationSuite extends FunSuite { } test("timestamp casting") { - val millis = 15 * 1000 + 1 + val millis = 15 * 1000 + 2 val ts = new Timestamp(millis) val ts1 = new Timestamp(15 * 1000) // a timestamp without the milliseconds part - checkEvaluation(ts cast ShortType, 15) - checkEvaluation(ts cast IntegerType, 15) - checkEvaluation(ts cast LongType, 15) - checkEvaluation(ts cast FloatType, 15.001f) - checkEvaluation(ts cast DoubleType, 15.001) + checkEvaluation(Cast(ts, ShortType), 15) + checkEvaluation(Cast(ts, IntegerType), 15) + checkEvaluation(Cast(ts, LongType), 15) + checkEvaluation(Cast(ts, FloatType), 15.002f) + checkEvaluation(Cast(ts, DoubleType), 15.002) checkEvaluation(Cast(Cast(ts, ShortType), TimestampType), ts1) checkEvaluation(Cast(Cast(ts, IntegerType), TimestampType), ts1) checkEvaluation(Cast(Cast(ts, LongType), TimestampType), ts1) @@ -261,6 +261,9 @@ class ExpressionEvaluationSuite extends FunSuite { checkEvaluation(Cast(Cast(millis.toDouble / 1000, TimestampType), DoubleType), millis.toDouble / 1000) checkEvaluation(Cast(Literal(BigDecimal(1)) cast TimestampType, DecimalType), 1) + + // A test for higher precision than millis + checkEvaluation(Cast(Cast(0.00000001, TimestampType), DoubleType), 0.00000001) } }