Skip to content

Commit eb2e62f

Browse files
han-yan01meta-codesync[bot]
authored andcommitted
feat: Add support for second with TIME type (facebookincubator#15058)
Summary: Pull Request resolved: facebookincubator#15058 - dded new `call` method handling `arg_type<Time>` input - TIME values stored as milliseconds since midnight (0-86399999 range) - Extracts seconds using: `(time / kMillisecondsInSecond) % 60` - Includes input validation for valid TIME range Reviewed By: duxiao1212 Differential Revision: D83989772 fbshipit-source-id: 3abae3cf2f2c4af6eb6adff4774b1402d0c10318
1 parent 6f69159 commit eb2e62f

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

velox/functions/prestosql/DateTimeFunctions.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,16 @@ struct SecondFunction : public TimestampWithTimezoneSupport<T> {
952952
auto timestamp = this->toTimestamp(timestampWithTimezone);
953953
result = getDateTime(timestamp, nullptr).tm_sec;
954954
}
955+
956+
FOLLY_ALWAYS_INLINE void call(int64_t& result, const arg_type<Time>& time) {
957+
VELOX_USER_CHECK(
958+
time >= 0 && time < kMillisInDay,
959+
"TIME value {} is out of range [0, 86400000)",
960+
time);
961+
auto duration = std::chrono::milliseconds(time);
962+
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
963+
result = seconds.count() % kSecondsInMinute;
964+
}
955965
};
956966

957967
template <typename T>

velox/functions/prestosql/registration/DateTimeFunctionsRegistration.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ void registerSimpleFunctions(const std::string& prefix) {
231231
registerFunction<SecondFunction, int64_t, Date>({prefix + "second"});
232232
registerFunction<SecondFunction, int64_t, TimestampWithTimezone>(
233233
{prefix + "second"});
234+
registerFunction<SecondFunction, int64_t, Time>({prefix + "second"});
234235
registerFunction<SecondFromIntervalFunction, int64_t, IntervalDayTime>(
235236
{prefix + "second"});
236237

velox/functions/prestosql/tests/DateTimeFunctionsTest.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,52 @@ TEST_F(DateTimeFunctionsTest, secondTimestampWithTimezone) {
19151915
59, secondTimestampWithTimezone(TimestampWithTimezone(-1000, "+05:30")));
19161916
}
19171917

1918+
TEST_F(DateTimeFunctionsTest, secondTime) {
1919+
const auto second = [&](std::optional<int64_t> time) {
1920+
return evaluateOnce<int64_t>("second(c0)", TIME(), time);
1921+
};
1922+
1923+
// null handling
1924+
EXPECT_EQ(std::nullopt, second(std::nullopt));
1925+
1926+
// boundary tests - optimization: (time / 1000) % 60
1927+
// lower boundary: 0 <= time < 86400000
1928+
EXPECT_EQ(0, second(0)); // exactly midnight - 00:00:00.000
1929+
EXPECT_EQ(0, second(999)); // 00:00:00.999 - last millisecond of second 0
1930+
EXPECT_EQ(1, second(1000)); // 00:00:01.000 - first millisecond of second 1
1931+
EXPECT_EQ(59, second(59000)); // 00:00:59.000 - first millisecond of second 59
1932+
EXPECT_EQ(0, second(60000)); // 00:01:00.000 - first second of next minute
1933+
EXPECT_EQ(59, second(86399000)); // 23:59:59.000
1934+
EXPECT_EQ(59, second(86399999)); // 23:59:59.999 - upper boundary exclusive
1935+
1936+
// representative test cases across different times
1937+
EXPECT_EQ(30, second(30000)); // 00:00:30.000
1938+
EXPECT_EQ(15, second(75000)); // 00:01:15.000
1939+
// 01:01:25 = 3600000 + 60000 + 25000 = 3685000
1940+
EXPECT_EQ(25, second(3685000)); // 01:01:25.000
1941+
EXPECT_EQ(3, second(3723123)); // 01:02:03.123
1942+
1943+
// verify optimization correctness with modulo boundary conditions
1944+
// seconds should cycle every 60 seconds regardless of hours/minutes
1945+
EXPECT_EQ(0, second(3600000)); // 01:00:00.000
1946+
EXPECT_EQ(30, second(3630000)); // 01:00:30.000
1947+
EXPECT_EQ(0, second(7200000)); // 02:00:00.000
1948+
EXPECT_EQ(45, second(43245000)); // 12:00:45.000
1949+
1950+
// test millisecond precision is correctly truncated
1951+
EXPECT_EQ(15, second(15123)); // 00:00:15.123
1952+
EXPECT_EQ(15, second(15999)); // 00:00:15.999
1953+
1954+
// error conditions - invalid range validation
1955+
EXPECT_THROW(second(-1), VeloxUserError); // negative time
1956+
EXPECT_THROW(
1957+
second(86400000),
1958+
VeloxUserError); // exactly 24:00:00.000 (exclusive upper bound)
1959+
EXPECT_THROW(
1960+
second(std::numeric_limits<int64_t>::max()),
1961+
VeloxUserError); // overflow case
1962+
}
1963+
19181964
TEST_F(DateTimeFunctionsTest, millisecond) {
19191965
const auto millisecond = [&](std::optional<Timestamp> timestamp) {
19201966
return evaluateOnce<int64_t>("millisecond(c0)", timestamp);

0 commit comments

Comments
 (0)