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
12 changes: 12 additions & 0 deletions cpp/include/cudf/datetime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,18 @@ 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());

/**
* `column[i]`. It will be null` if the input row at `column[i]` is null.
shaneding marked this conversation as resolved.
Show resolved Hide resolved
shaneding marked this conversation as resolved.
Show resolved Hide resolved
*
* @throw cudf::logic_error if input column datatype is not a TIMESTAMP
*
* @param The input column containing datetime values
* @return A column of INT16 type indicating which quarter the date is in
*/
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
31 changes: 31 additions & 0 deletions cpp/src/datetime/datetime_ops.cu
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,23 @@ struct extract_day_num_of_year {
}
};

// Extract the the quarter to which the timestamp belongs to
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()};

// (x + y - 1) / y = ceil(x/y), where x and y are unsigned. x = month, y = 3
return (month + 2) / 3;
}
};

struct is_leap_year_op {
template <typename Timestamp>
CUDA_DEVICE_CALLABLE bool operator()(Timestamp const ts) const
Expand Down Expand Up @@ -376,6 +393,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 +476,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
38 changes: 37 additions & 1 deletion cpp/tests/datetime/datetime_ops_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <cudf_test/base_fixture.hpp>
#include <cudf_test/column_utilities.hpp>
#include <cudf_test/column_wrapper.hpp>
#include <cudf_test/iterator_utilities.hpp>
#include <cudf_test/timestamp_utilities.cuh>
#include <cudf_test/type_lists.hpp>

Expand Down Expand Up @@ -552,7 +553,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 @@ -569,4 +570,39 @@ 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;
using namespace cudf::test::iterators;

// 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
0L, // null
915148800L, // 1999-01-01 00:00:00 GMT
-11663029161L, // 1600-5-31 05:40:39 GMT
707904541L, // 1992-06-07 08:09:01 GMT
-2181005247L, // 1900-11-20 09:12:33 GMT
0L, // UNIX EPOCH 1970-01-01 00:00:00 GMT
-12212553600L, // First full year of Gregorian Calandar 1583-01-01 00:00:00
0L, // null
13591632822L, // 2400-09-13 13:33:42 GMT
4539564243L, // 2113-11-08 06:04:03 GMT
0L, // null
1608581568L, // 2020-12-21 08:12:48 GMT
1584821568L, // 2020-03-21 08:12:48 GMT
},
nulls_at({1, 8, 11})};

auto quarter = cudf::test::fixed_width_column_wrapper<int16_t>{
{3, 0 /*null*/, 1, 2, 2, 4, 1, 1, 0 /*null*/, 3, 4, 0 /*null*/, 4, 1}, nulls_at({1, 8, 11})};

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

CUDF_TEST_PROGRAM_MAIN()