Skip to content

Commit 9304499

Browse files
committed
Add date_diff Spark function (5993)
1 parent 7e8cbec commit 9304499

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

velox/docs/functions/spark/datetime.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ These functions support TIMESTAMP and DATE input types.
1313
If num_days is a negative value then these amount of days will be
1414
deducted from start_date.
1515

16+
.. spark:function:: date_diff(endDate, startDate) -> integer
17+
Returns the number of days from startDate to endDate.
18+
``datediff`` is` an alias for ``date_diff``::
19+
20+
SELECT date_diff('2009-07-31', '2009-07-30'); -- 1
21+
SELECT date_diff('2009-07-30', '2009-07-31'); -- -1
22+
1623
.. spark:function:: date_sub(start_date, num_days) -> date
1724
1825
Returns the date that is num_days before start_date. According to the inputs,

velox/functions/sparksql/DateTimeFunctions.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,4 +319,20 @@ struct DayOfWeekFunction : public InitSessionTimezone<T>,
319319
}
320320
};
321321

322+
template <typename T>
323+
struct DateDiffFunction {
324+
VELOX_DEFINE_FUNCTION_TYPES(T);
325+
326+
FOLLY_ALWAYS_INLINE bool call(
327+
int32_t& result,
328+
const arg_type<Date>& endDate,
329+
const arg_type<Date>& startDate) {
330+
int64_t value = diffDate(DateTimeUnit::kDay, startDate, endDate);
331+
if (value != (int32_t)value) {
332+
VELOX_UNSUPPORTED("integer overflow");
333+
}
334+
result = (int32_t)value;
335+
return true;
336+
}
337+
};
322338
} // namespace facebook::velox::functions::sparksql

velox/functions/sparksql/Register.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,10 @@ void registerFunctions(const std::string& prefix) {
233233
Varchar>({prefix + "unix_timestamp", prefix + "to_unix_timestamp"});
234234
registerFunction<MakeDateFunction, Date, int32_t, int32_t, int32_t>(
235235
{prefix + "make_date"});
236-
236+
registerFunction<DateDiffFunction, int32_t, Date, Date>(
237+
{prefix + "date_diff"});
238+
registerFunction<DateDiffFunction, int32_t, Date, Date>(
239+
{prefix + "datediff"});
237240
registerFunction<LastDayFunction, Date, Date>({prefix + "last_day"});
238241

239242
registerFunction<DateAddFunction, Date, Date, int32_t>({prefix + "date_add"});

velox/functions/sparksql/tests/DateTimeFunctionsTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,5 +379,41 @@ TEST_F(DateTimeFunctionsTest, dayofWeekTs) {
379379
}
380380
}
381381

382+
TEST_F(DateTimeFunctionsTest, dateDiffDate) {
383+
const auto dateDiff = [&](std::optional<int32_t> endDate,
384+
std::optional<int32_t> startDate) {
385+
return evaluateOnce<int32_t, int32_t>(
386+
"date_diff(c0, c1)", {endDate, startDate}, {DATE(), DATE()});
387+
};
388+
389+
const auto dateDiffAlias = [&](std::optional<int32_t> endDate,
390+
std::optional<int32_t> startDate) {
391+
return evaluateOnce<int32_t, int32_t>(
392+
"datediff(c0, c1)", {endDate, startDate}, {DATE(), DATE()});
393+
};
394+
// Check null behaviors
395+
EXPECT_EQ(std::nullopt, dateDiff(1, std::nullopt));
396+
EXPECT_EQ(std::nullopt, dateDiff(std::nullopt, 0));
397+
398+
// Simple tests
399+
EXPECT_EQ(-1, dateDiff(parseDate("2019-02-28"), parseDate("2019-03-01")));
400+
EXPECT_EQ(-358, dateDiff(parseDate("2019-02-28"), parseDate("2020-02-21")));
401+
EXPECT_EQ(0, dateDiff(parseDate("1994-04-20"), parseDate("1994-04-20")));
402+
403+
// Account for the last day of a year-month
404+
EXPECT_EQ(395, dateDiff(parseDate("2020-02-29"), parseDate("2019-01-30")));
405+
406+
// Check Large date
407+
EXPECT_EQ(
408+
-737790, dateDiff(parseDate("2020-02-29"), parseDate("4040-02-29")));
409+
410+
// Negative year
411+
EXPECT_EQ(
412+
2147474628,
413+
dateDiff(parseDate("-5877641-06-23"), parseDate("1994-09-12")));
414+
415+
EXPECT_EQ(0, dateDiffAlias(parseDate("1994-04-20"), parseDate("1994-04-20")));
416+
}
417+
382418
} // namespace
383419
} // namespace facebook::velox::functions::sparksql::test

0 commit comments

Comments
 (0)