diff --git a/velox/functions/prestosql/FromUnixTime.cpp b/velox/functions/prestosql/FromUnixTime.cpp index 946c1866be27..0d7f0d2dad6e 100644 --- a/velox/functions/prestosql/FromUnixTime.cpp +++ b/velox/functions/prestosql/FromUnixTime.cpp @@ -21,6 +21,9 @@ namespace facebook::velox::functions { namespace { inline int64_t toMillis(double unixtime) { + if (UNLIKELY(std::isnan(unixtime))) { + return 0; + } return std::floor(unixtime * 1'000); } diff --git a/velox/functions/prestosql/tests/DateTimeFunctionsTest.cpp b/velox/functions/prestosql/tests/DateTimeFunctionsTest.cpp index 4baaa36fbe0f..74b023341700 100644 --- a/velox/functions/prestosql/tests/DateTimeFunctionsTest.cpp +++ b/velox/functions/prestosql/tests/DateTimeFunctionsTest.cpp @@ -275,6 +275,8 @@ TEST_F(DateTimeFunctionsTest, fromUnixtimeRountTrip) { } TEST_F(DateTimeFunctionsTest, fromUnixtimeWithTimeZone) { + static const double kNan = std::numeric_limits::quiet_NaN(); + vector_size_t size = 37; auto unixtimeAt = [](vector_size_t row) -> double { @@ -295,6 +297,17 @@ TEST_F(DateTimeFunctionsTest, fromUnixtimeWithTimeZone) { makeConstant((int16_t)900, size), }); assertEqualVectors(expected, result); + + // NaN timestamp. + result = evaluate( + "from_unixtime(c0, '+01:00')", + makeRowVector({makeFlatVector({kNan, kNan})})); + ASSERT_TRUE(isTimestampWithTimeZoneType(result->type())); + expected = makeRowVector({ + makeFlatVector({0, 0}), + makeFlatVector({900, 900}), + }); + assertEqualVectors(expected, result); } // Variable timezone parameter. @@ -317,6 +330,20 @@ TEST_F(DateTimeFunctionsTest, fromUnixtimeWithTimeZone) { size, [&](auto row) { return timezoneIds[row % 5]; }), }); assertEqualVectors(expected, result); + + // NaN timestamp. + result = evaluate( + "from_unixtime(c0, c1)", + makeRowVector({ + makeFlatVector({kNan, kNan}), + makeNullableFlatVector({"+01:00", "+02:00"}), + })); + ASSERT_TRUE(isTimestampWithTimeZoneType(result->type())); + expected = makeRowVector({ + makeFlatVector({0, 0}), + makeFlatVector({900, 960}), + }); + assertEqualVectors(expected, result); } }