Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add quarters to libcudf datetime #8779

Merged
merged 11 commits into from
Jul 26, 2021
16 changes: 16 additions & 0 deletions cpp/include/cudf/datetime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,22 @@ std::unique_ptr<cudf::column> is_leap_year(
cudf::column_view const& column,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/**
* @brief Returns the quarter of the date
*
* `output[i] == true` if year of `column[i]` is a leap year
* `output[i] == false` if year of `column[i]` is not a leap year
* `output[i] is null` if `column[i]` is null
shaneding marked this conversation as resolved.
Show resolved Hide resolved
*
* @param[in] cudf::column_view of the input datetime values
shaneding marked this conversation as resolved.
Show resolved Hide resolved
*
* @returns cudf::column of datatype INT16 indicating which quarter the date is in
shaneding marked this conversation as resolved.
Show resolved Hide resolved
* @throw cudf::logic_error if input column datatype is not a TIMESTAMP
*/
std::unique_ptr<cudf::column> extract_quarter(
cudf::column_view const& column,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/** @} */ // end of group
} // namespace datetime
} // namespace cudf
5 changes: 5 additions & 0 deletions cpp/include/cudf/detail/datetime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ std::unique_ptr<cudf::column> is_leap_year(
rmm::cuda_stream_view stream = rmm::cuda_stream_default,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

std::unique_ptr<cudf::column> extract_quarter(
cudf::column_view const& column,
rmm::cuda_stream_view stream = rmm::cuda_stream_default,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

} // namespace detail
} // namespace datetime
} // namespace cudf
33 changes: 33 additions & 0 deletions cpp/src/datetime/datetime_ops.cu
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,25 @@ struct extract_day_num_of_year {
}
};

// Extract the day number of the year present in the timestamp
shaneding marked this conversation as resolved.
Show resolved Hide resolved
struct extract_quarter_op {
template <typename Timestamp>
CUDA_DEVICE_CALLABLE int16_t operator()(Timestamp const ts) const
shaneding marked this conversation as resolved.
Show resolved Hide resolved
{
using namespace cuda::std::chrono;

// Only has the days - time component is chopped off, which is what we want
auto const days_since_epoch = floor<days>(ts);
auto const date = year_month_day(days_since_epoch);
auto const month = unsigned{date.month()};

if (month <= 3) return 1;
if (month <= 6) return 2;
if (month <= 9) return 3;
return 4;
shaneding marked this conversation as resolved.
Show resolved Hide resolved
}
};

struct is_leap_year_op {
template <typename Timestamp>
CUDA_DEVICE_CALLABLE bool operator()(Timestamp const ts) const
Expand Down Expand Up @@ -376,6 +395,13 @@ std::unique_ptr<column> is_leap_year(column_view const& column,
return apply_datetime_op<is_leap_year_op, type_id::BOOL8>(column, stream, mr);
}

std::unique_ptr<column> extract_quarter(column_view const& column,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr)
{
return apply_datetime_op<extract_quarter_op, type_id::INT16>(column, stream, mr);
isVoid marked this conversation as resolved.
Show resolved Hide resolved
}

} // namespace detail

std::unique_ptr<column> extract_year(column_view const& column, rmm::mr::device_memory_resource* mr)
Expand Down Expand Up @@ -452,5 +478,12 @@ std::unique_ptr<column> is_leap_year(column_view const& column, rmm::mr::device_
return detail::is_leap_year(column, rmm::cuda_stream_default, mr);
}

std::unique_ptr<column> extract_quarter(column_view const& column,
rmm::mr::device_memory_resource* mr)
{
CUDF_FUNC_RANGE();
return detail::extract_quarter(column, rmm::cuda_stream_default, mr);
}

} // namespace datetime
} // namespace cudf
35 changes: 34 additions & 1 deletion cpp/tests/datetime/datetime_ops_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ TEST_F(BasicDatetimeOpsTest, TestIsLeapYear)
915148800L, // 1999-01-01 00:00:00 GMT - non leap year
-11663029161L, // 1600-5-31 05:40:39 GMT - leap year
707904541L, // 1992-06-07 08:09:01 GMT - leap year
2181048447L, // 1900-11-20 09:12:33 GMT - non leap year
-2181005247L, // 1900-11-20 09:12:33 GMT - non leap year
0L, // UNIX EPOCH 1970-01-01 00:00:00 GMT - non leap year
-12212553600L, // First full year of Gregorian Calandar 1583-01-01 00:00:00 - non-leap-year
0L, // null
Expand All @@ -567,4 +567,37 @@ TEST_F(BasicDatetimeOpsTest, TestIsLeapYear)
{true, false, true, true, true, true, true, true, false, true, true, false}});
}

TEST_F(BasicDatetimeOpsTest, TestQuarter)
{
using namespace cudf::test;
using namespace cudf::datetime;
using namespace cuda::std::chrono;

// Time in seconds since epoch
// Dates converted using epochconverter.com
auto timestamps_s =
cudf::test::fixed_width_column_wrapper<cudf::timestamp_s, cudf::timestamp_s::rep>{
{
1594332839L, // 2020-07-09 10:13:59 GMT - leap year
0L, // null
915148800L, // 1999-01-01 00:00:00 GMT - non leap year
-11663029161L, // 1600-5-31 05:40:39 GMT - leap year
707904541L, // 1992-06-07 08:09:01 GMT - leap year
-2181005247L, // 1900-11-20 09:12:33 GMT - non leap year
0L, // UNIX EPOCH 1970-01-01 00:00:00 GMT - non leap year
-12212553600L, // First full year of Gregorian Calandar 1583-01-01 00:00:00 - non-leap-year
0L, // null
13591632822L, // 2400-09-13 13:33:42 GMT - leap year
4539564243L, // 2113-11-08 06:04:03 GMT - non leap year
0L // null
},
{true, false, true, true, true, true, true, true, false, true, true, false}};

auto quarter = cudf::test::fixed_width_column_wrapper<int16_t>{
{3, 6, 1, 2, 2, 4, 1, 1, 1, 3, 4, 3},
{true, false, true, true, true, true, true, true, false, true, true, false}};

CUDF_TEST_EXPECT_COLUMNS_EQUAL(*extract_quarter(timestamps_s), quarter);
}

CUDF_TEST_PROGRAM_MAIN()