diff --git a/.github/workflows/conda-python-build.yaml b/.github/workflows/conda-python-build.yaml index fb775be..4f5df6f 100644 --- a/.github/workflows/conda-python-build.yaml +++ b/.github/workflows/conda-python-build.yaml @@ -41,7 +41,7 @@ jobs: PY_VER: - "3.10" - "3.11" - # - "3.12" requires update to RAPIDS 24.10 + - "3.12" runs-on: linux-${{ matrix.ARCH }}-cpu4 container: image: "rapidsai/ci-conda:cuda${{ matrix.CUDA_VER }}-ubuntu22.04-py${{ matrix.PY_VER }}" diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 067b8b8..6a07e94 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -48,7 +48,7 @@ jobs: # # * architectures: amd64 only # * CUDA: >=12.2 - # * Python: 3.10, 3.11, 3.12 + # * Python: 3.10, 3.11, 3.12 (3.11 used in doc building) # # Valid set of RAPIDS ci-conda image tags: https://hub.docker.com/r/rapidsai/ci-conda/tags matrix: @@ -56,6 +56,9 @@ jobs: - ARCH: "amd64" CUDA_VER: "12.5.1" PY_VER: "3.10" + - ARCH: "amd64" + CUDA_VER: "12.5.1" + PY_VER: "3.12" runs-on: linux-${{ matrix.ARCH }}-gpu-v100-latest-1 container: image: "rapidsai/ci-conda:cuda${{ matrix.CUDA_VER }}-ubuntu22.04-py${{ matrix.PY_VER }}" diff --git a/ci/run_ctests.sh b/ci/run_ctests.sh index 42de590..719f7ef 100755 --- a/ci/run_ctests.sh +++ b/ci/run_ctests.sh @@ -11,13 +11,8 @@ else cd "${INSTALL_PREFIX:-${CONDA_PREFIX:-/usr}}/bin/gtests/liblegate_dataframe/" fi -# Unless otherwise specified, use all available GPUs and set +# Unless `LEGATE_CONFIG` is set, default to all available GPUs and set fbmem/sysmem. # LEGATE_TEST=1 to test broadcasting code paths (locally). -# TODO: Set LEGATE_CONFIG instead (if undefined). However, -# as of 2024-10-11 LEGATE_CONFIG seems broken: -# https://github.com/nv-legate/legate.core.internal/issues/1304 +LEGATE_CONFIG=${LEGATE_CONFIG:- --gpus="$(nvidia-smi -L | wc -l) --fbmem=4000 --sysmem=4000"} \ LEGATE_TEST=${LEGATE_TEST:-1} \ -legate \ - --gpus "$(nvidia-smi -L | wc -l)" \ - --fbmem=4000 --sysmem=4000 \ - ./cpp_tests --output-on-failure --no-tests=error "$@" +legate ./cpp_tests --output-on-failure --no-tests=error "$@" diff --git a/ci/run_pytests.sh b/ci/run_pytests.sh index dc3a03d..5577b75 100755 --- a/ci/run_pytests.sh +++ b/ci/run_pytests.sh @@ -18,15 +18,11 @@ set -e -E -u -o pipefail # Support invoking run_cudf_pytests.sh outside the script directory cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")"/../python/tests/ -# Unless otherwise specified, use all available GPUs and set +# Unless `LEGATE_CONFIG` is set, default to all available GPUs and set fbmem/sysmem. # LEGATE_TEST=1 to test broadcasting code paths (locally). -# TODO: Set LEGATE_CONFIG instead (if undefined). However, -# as of 2024-10-11 LEGATE_CONFIG seems broken: -# https://github.com/nv-legate/legate.core.internal/issues/1304 +LEGATE_CONFIG=${LEGATE_CONFIG:- --gpus="$(nvidia-smi -L | wc -l) --fbmem=4000 --sysmem=4000"} \ LEGATE_TEST=${LEGATE_TEST:-1} \ legate \ - --gpus "$(nvidia-smi -L | wc -l)"\ - --fbmem=4000 \ --module pytest \ . \ -sv \ diff --git a/conda/environments/all_cuda-124_arch-x86_64.yaml b/conda/environments/all_cuda-124_arch-x86_64.yaml index 5e17e46..008fc15 100644 --- a/conda/environments/all_cuda-124_arch-x86_64.yaml +++ b/conda/environments/all_cuda-124_arch-x86_64.yaml @@ -17,24 +17,24 @@ dependencies: - cuda-profiler-api - cuda-sanitizer-api - cuda-version=12.4 -- cudf==24.10.*,>=0.0.0a0 +- cudf==24.12.*,>=0.0.0a0 - cupy>=12.0.0 - cupynumeric==25.01.*,>=0.0.0.dev0 - cxx-compiler - cython>=3.0.3 -- dask-cuda==24.10.* -- dask-cudf==24.10.* +- dask-cuda==24.12.* +- dask-cudf==24.12.* - gcc_linux-64=11.* - legate==25.01.*,>=0.0.0.dev0 -- libcudf==24.10.*,>=0.0.0a0 -- librmm==24.10.*,>=0.0.0a0 +- libcudf==24.12.*,>=0.0.0a0 +- librmm==24.12.*,>=0.0.0a0 - make - myst-parser>=4.0 - ninja - numpy >=1.23,<3.0.0a0 - openssh - pydata-sphinx-theme>=0.16.0 -- pylibcudf==24.10.*,>=0.0.0a0 +- pylibcudf==24.12.*,>=0.0.0a0 - pytest>=7.0 - python>=3.10,<3.13 - rapids-build-backend>=0.3.2,<0.4.0.dev0 diff --git a/conda/recipes/legate-dataframe/conda_build_config.yaml b/conda/recipes/legate-dataframe/conda_build_config.yaml index 60e70f5..f6c1a3d 100644 --- a/conda/recipes/legate-dataframe/conda_build_config.yaml +++ b/conda/recipes/legate-dataframe/conda_build_config.yaml @@ -22,5 +22,10 @@ cuda11_compiler: legate_version: - "=25.01.*,>=0.0.0.dev0" +# TODO: The != temporary blocklist cupynumeric versions +# using cupynumeric, because it is fewer versions to block. +cupynumeric_version: + - "=25.01.*,>=0.0.0.dev0,!=25.01.0.dev62,!=25.01.0.dev61,!=25.01.0.dev60,!=25.01.0.rc1" + rapids_version: - - =24.10.* + - =24.12.* diff --git a/conda/recipes/legate-dataframe/meta.yaml b/conda/recipes/legate-dataframe/meta.yaml index 627e58a..11f8bb4 100644 --- a/conda/recipes/legate-dataframe/meta.yaml +++ b/conda/recipes/legate-dataframe/meta.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2024, NVIDIA CORPORATION. +# Copyright (c) 2024-2025, NVIDIA CORPORATION. {% set pyproject_data = load_file_data("python/pyproject.toml") %} {% set version = environ['LEGATEDATAFRAME_PACKAGE_VERSION'] %} @@ -60,7 +60,7 @@ requirements: # Only to ensure a nightly legate version we pick up # is compatible with an existing cupynumeric version. # (may also stabilize not using debug/sanitizer builds) - - cupynumeric + - cupynumeric {{ cupynumeric_version }} - python - pip - cython >=3.0.3 diff --git a/cpp/cmake/fetch_rapids.cmake b/cpp/cmake/fetch_rapids.cmake index 4e457c1..d72b0f6 100644 --- a/cpp/cmake/fetch_rapids.cmake +++ b/cpp/cmake/fetch_rapids.cmake @@ -12,7 +12,7 @@ # the License. # ============================================================================= if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/LEGATE_DATAFRAME_RAPIDS.cmake) - file(DOWNLOAD https://raw.githubusercontent.com/rapidsai/rapids-cmake/branch-24.10/RAPIDS.cmake + file(DOWNLOAD https://raw.githubusercontent.com/rapidsai/rapids-cmake/branch-24.12/RAPIDS.cmake ${CMAKE_CURRENT_BINARY_DIR}/LEGATE_DATAFRAME_RAPIDS.cmake ) endif() diff --git a/cpp/cmake/thirdparty/get_cudf.cmake b/cpp/cmake/thirdparty/get_cudf.cmake index c625024..a63e9bf 100644 --- a/cpp/cmake/thirdparty/get_cudf.cmake +++ b/cpp/cmake/thirdparty/get_cudf.cmake @@ -51,5 +51,5 @@ function(find_and_configure_cudf) endfunction() find_and_configure_cudf( - VERSION 24.10 GIT_REPO https://github.com/rapidsai/cudf.git GIT_TAG branch-24.10 + VERSION 24.12 GIT_REPO https://github.com/rapidsai/cudf.git GIT_TAG branch-24.12 ) diff --git a/cpp/include/legate_dataframe/timestamps.hpp b/cpp/include/legate_dataframe/timestamps.hpp index 90beaf1..615568b 100644 --- a/cpp/include/legate_dataframe/timestamps.hpp +++ b/cpp/include/legate_dataframe/timestamps.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, NVIDIA CORPORATION. + * Copyright (c) 2023-2025, NVIDIA CORPORATION. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ #include +#include #include #include @@ -79,20 +80,6 @@ LogicalColumn to_timestamps(const LogicalColumn& input, cudf::data_type timestamp_type, std::string format); -enum class DatetimeComponent : int32_t { - year, - month, - day, - weekday, - hour, - minute, - second, - millisecond_fraction, - microsecond_fraction, - nanosecond_fraction, - day_of_year -}; - /** * @brief Extracts part of a timestamp as a int16. * @@ -100,6 +87,7 @@ enum class DatetimeComponent : int32_t { * @param component The component which to extract. * @return New int16 column. */ -LogicalColumn extract_timestamp_component(const LogicalColumn& input, DatetimeComponent component); +LogicalColumn extract_timestamp_component(const LogicalColumn& input, + cudf::datetime::datetime_component component); } // namespace legate::dataframe diff --git a/cpp/src/timestamps.cpp b/cpp/src/timestamps.cpp index e5fdfaf..d71b55d 100644 --- a/cpp/src/timestamps.cpp +++ b/cpp/src/timestamps.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, NVIDIA CORPORATION. + * Copyright (c) 2023-2025, NVIDIA CORPORATION. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,7 @@ #include -// cudf's detail API of datetime assume that RMM has been included -#include - -#include +#include #include #include @@ -52,52 +49,13 @@ class ExtractTimestampComponentTask static void gpu_variant(legate::TaskContext context) { GPUTaskContext ctx{context}; - const auto component = - argument::get_next_scalar>(ctx); - const auto input = argument::get_next_input(ctx); - auto output = argument::get_next_output(ctx); + const auto component = argument::get_next_scalar(ctx); + const auto input = argument::get_next_input(ctx); + auto output = argument::get_next_output(ctx); std::unique_ptr ret; - /* unfortunately, there seems to be no templating for this in libcudf: */ - switch (static_cast(component)) { - case DatetimeComponent::year: - ret = cudf::datetime::detail::extract_year(input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::month: - ret = cudf::datetime::detail::extract_month(input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::day: - ret = cudf::datetime::detail::extract_day(input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::weekday: - ret = cudf::datetime::detail::extract_weekday(input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::hour: - ret = cudf::datetime::detail::extract_hour(input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::minute: - ret = cudf::datetime::detail::extract_minute(input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::second: - ret = cudf::datetime::detail::extract_second(input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::millisecond_fraction: - ret = cudf::datetime::detail::extract_millisecond_fraction( - input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::microsecond_fraction: - ret = cudf::datetime::detail::extract_microsecond_fraction( - input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::nanosecond_fraction: - ret = cudf::datetime::detail::extract_nanosecond_fraction( - input.column_view(), ctx.stream(), ctx.mr()); - break; - case DatetimeComponent::day_of_year: - ret = cudf::datetime::detail::day_of_year(input.column_view(), ctx.stream(), ctx.mr()); - break; - default: throw std::runtime_error("invalid resolution to time part extraction?"); - } + ret = cudf::datetime::extract_datetime_component( + input.column_view(), component, ctx.stream(), ctx.mr()); output.move_into(std::move(ret)); } @@ -119,7 +77,8 @@ LogicalColumn to_timestamps(const LogicalColumn& input, return ret; } -LogicalColumn extract_timestamp_component(const LogicalColumn& input, DatetimeComponent component) +LogicalColumn extract_timestamp_component(const LogicalColumn& input, + cudf::datetime::datetime_component component) { if (!cudf::is_timestamp(input.cudf_type())) { throw std::invalid_argument("extract_timestamp_component() input must be timestamp"); @@ -128,8 +87,8 @@ LogicalColumn extract_timestamp_component(const LogicalColumn& input, DatetimeCo auto ret = LogicalColumn::empty_like(cudf::data_type{cudf::type_id::INT16}, input.nullable()); legate::AutoTask task = runtime->create_task(get_library(), task::ExtractTimestampComponentTask::TASK_ID); - argument::add_next_scalar(task, - static_cast>(component)); + argument::add_next_scalar( + task, static_cast>(component)); argument::add_next_input(task, input); argument::add_next_output(task, ret); runtime->submit(std::move(task)); diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 4dcc562..150e694 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -34,10 +34,13 @@ set_target_properties( CUDA_STANDARD_REQUIRED ON ) +set(LDF_TEST_CUDA_FLAGS --expt-extended-lambda --expt-relaxed-constexpr) +target_compile_options(cpp_tests PRIVATE "$<$:${LDF_TEST_CUDA_FLAGS}>") + # Note that fmt::fmt should not be required, but seems to be for debug builds. target_link_libraries( - cpp_tests PRIVATE LegateDataframe cudf cudf::cudftestutil GTest::gmock GTest::gtest fmt::fmt - $ + cpp_tests PRIVATE LegateDataframe cudf cudf::cudftestutil cudf::cudftestutil_impl + GTest::gmock GTest::gtest fmt::fmt $ ) rapids_test_add( NAME cpp_tests diff --git a/dependencies.yaml b/dependencies.yaml index 5dfe2e6..40954f1 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -175,8 +175,8 @@ dependencies: packages: - cupynumeric==25.01.*,>=0.0.0.dev0 - pytest>=7.0 - - dask-cuda==24.10.* - - dask-cudf==24.10.* + - dask-cuda==24.12.* + - dask-cudf==24.12.* - output_types: conda packages: - cuda-sanitizer-api @@ -187,8 +187,8 @@ dependencies: common: - output_types: conda packages: - - &cudf_unsuffixed cudf==24.10.*,>=0.0.0a0 - - &pylibcudf_unsuffixed pylibcudf==24.10.*,>=0.0.0a0 + - &cudf_unsuffixed cudf==24.12.*,>=0.0.0a0 + - &pylibcudf_unsuffixed pylibcudf==24.12.*,>=0.0.0a0 specific: - output_types: [requirements, pyproject] matrices: @@ -196,8 +196,8 @@ dependencies: cuda: "12.*" cuda_suffixed: "true" packages: - - cudf-cu12==24.10.*,>=0.0.0a0 - - pylibcudf-cu12==24.10.*,>=0.0.0a0 + - cudf-cu12==24.12.*,>=0.0.0a0 + - pylibcudf-cu12==24.12.*,>=0.0.0a0 - {matrix: null, packages: [*cudf_unsuffixed, *pylibcudf_unsuffixed]} depends_on_cupy: @@ -223,7 +223,7 @@ dependencies: common: - output_types: conda packages: - - &libcudf_unsuffixed libcudf==24.10.*,>=0.0.0a0 + - &libcudf_unsuffixed libcudf==24.12.*,>=0.0.0a0 specific: - output_types: [requirements, pyproject] matrices: @@ -231,14 +231,14 @@ dependencies: cuda: "12.*" cuda_suffixed: "true" packages: - - libcudf-cu12==24.10.*,>=0.0.0a0 + - libcudf-cu12==24.12.*,>=0.0.0a0 - {matrix: null, packages: [*libcudf_unsuffixed]} depends_on_librmm: common: - output_types: conda packages: - - &librmm_unsuffixed librmm==24.10.*,>=0.0.0a0 + - &librmm_unsuffixed librmm==24.12.*,>=0.0.0a0 specific: - output_types: [requirements, pyproject] matrices: @@ -246,7 +246,7 @@ dependencies: cuda: "12.*" cuda_suffixed: "true" packages: - - librmm-cu12==24.10.*,>=0.0.0a0 + - librmm-cu12==24.12.*,>=0.0.0a0 - matrix: packages: - *librmm_unsuffixed diff --git a/python/legate_dataframe/lib/timestamps.pyi b/python/legate_dataframe/lib/timestamps.pyi index 2774599..b31ebaf 100644 --- a/python/legate_dataframe/lib/timestamps.pyi +++ b/python/legate_dataframe/lib/timestamps.pyi @@ -2,15 +2,18 @@ # SPDX-License-Identifier: Apache-2.0 from numpy.typing import DTypeLike +from pylibcudf.datetime import DatetimeComponent from legate_dataframe.lib.core.column import LogicalColumn +__all__ = ["to_timestamps", "extract_timestamp_component", "DatetimeComponent"] + def to_timestamps( col: LogicalColumn, timestamp_type: DTypeLike, format_pattern: str, ) -> LogicalColumn: ... -def extract_timepart( +def extract_timestamp_component( col: LogicalColumn, - resolution: str, + component: DatetimeComponent, ) -> LogicalColumn: ... diff --git a/python/legate_dataframe/lib/timestamps.pyx b/python/legate_dataframe/lib/timestamps.pyx index c5f9d38..4284551 100644 --- a/python/legate_dataframe/lib/timestamps.pyx +++ b/python/legate_dataframe/lib/timestamps.pyx @@ -1,42 +1,25 @@ -# Copyright (c) 2023-2024, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2023-2025, NVIDIA CORPORATION. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # distutils: language = c++ # cython: language_level=3 -from libc.stdint cimport int32_t from libcpp.string cimport string +from pylibcudf.libcudf.datetime cimport datetime_component from pylibcudf.types cimport data_type from legate_dataframe.lib.core.column cimport LogicalColumn, cpp_LogicalColumn from legate_dataframe.lib.core.data_type cimport as_data_type from numpy.typing import DTypeLike +from pylibcudf.datetime import DatetimeComponent # no-cython-lint from legate_dataframe.utils import _track_provenance cdef extern from "" namespace "legate::dataframe": - cpdef enum class DatetimeComponent(int32_t): - """Datetime component to extract, can be one of: - ``year``, ``months``, ``day``, ``weekday``, ``hour``, ``minute``, - ``second``, ``millisecond_fraction``, ``microsecond_fraction``, - ``nanosecond_fraction``, and ``day_of_year``. - """ - year - month - day - weekday - hour - minute - second - millisecond_fraction - microsecond_fraction - nanosecond_fraction - day_of_year - cpp_LogicalColumn cpp_to_timestamps "to_timestamps"( const cpp_LogicalColumn& input, data_type timestamp_type, @@ -45,7 +28,7 @@ cdef extern from "" namespace "legate::datafram cpp_LogicalColumn cpp_extract_timestamp_component "extract_timestamp_component"( const cpp_LogicalColumn& input, - DatetimeComponent component, + datetime_component component, ) @@ -97,7 +80,7 @@ def to_timestamps( @_track_provenance def extract_timestamp_component( LogicalColumn col, - field: DatetimeComponent, + datetime_component component, ) -> LogicalColumn: """ Extract part of the timestamp as int16. @@ -106,9 +89,8 @@ def extract_timestamp_component( ---------- col : LogicalColumn Column of timestamps - field - The field/resolution to extract. Must be specified as a - ``DatetimeComponent``. + component + The component to extract. Must be specified as a ``DatetimeComponent``. Returns ------- @@ -122,5 +104,5 @@ def extract_timestamp_component( """ return LogicalColumn.from_handle( - cpp_extract_timestamp_component(col._handle, field) + cpp_extract_timestamp_component(col._handle, component) ) diff --git a/python/pyproject.toml b/python/pyproject.toml index 69cf319..8d1111d 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -20,10 +20,10 @@ description = "Basic cudf operations on Legate" license = {text = "Apache 2.0"} requires-python = ">=3.10" dependencies = [ - "cudf==24.10.*,>=0.0.0a0", + "cudf==24.12.*,>=0.0.0a0", "legate==25.01.*,>=0.0.0.dev0", "numpy >=1.23,<3.0.0a0", - "pylibcudf==24.10.*,>=0.0.0a0", + "pylibcudf==24.12.*,>=0.0.0a0", ] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../dependencies.yaml and run `rapids-dependency-file-generator`. [project.urls] @@ -34,8 +34,8 @@ License = "https://github.com/rapidsai/legate-dataframe/blob/main/LICENSE" [project.optional-dependencies] test = [ "cupynumeric==25.01.*,>=0.0.0.dev0", - "dask-cuda==24.10.*", - "dask-cudf==24.10.*", + "dask-cuda==24.12.*", + "dask-cudf==24.12.*", "pytest>=7.0", ] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../dependencies.yaml and run `rapids-dependency-file-generator`. @@ -54,7 +54,7 @@ requires = [ "cmake>=3.26.4,!=3.30.0", "cython>=3.0.3", "legate==25.01.*,>=0.0.0.dev0", - "libcudf==24.10.*,>=0.0.0a0", + "libcudf==24.12.*,>=0.0.0a0", "ninja", ] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../dependencies.yaml and run `rapids-dependency-file-generator`. diff --git a/python/tests/test_timestamps.py b/python/tests/test_timestamps.py index 6d8f30e..c0dbcfa 100644 --- a/python/tests/test_timestamps.py +++ b/python/tests/test_timestamps.py @@ -61,33 +61,37 @@ def test_to_timestamps(df, timestamp_type): @pytest.mark.parametrize( "field", [ - DatetimeComponent.year, - DatetimeComponent.month, - DatetimeComponent.day, - DatetimeComponent.weekday, - DatetimeComponent.hour, - DatetimeComponent.minute, - DatetimeComponent.second, - # Cudf/pandas microsecond includes the milliseconds (so doesn't exist): - # DatetimeComponent.millisecond_fraction, - DatetimeComponent.microsecond_fraction, - DatetimeComponent.nanosecond_fraction, - DatetimeComponent.day_of_year, + DatetimeComponent.YEAR, + DatetimeComponent.MONTH, + DatetimeComponent.DAY, + DatetimeComponent.WEEKDAY, + DatetimeComponent.HOUR, + DatetimeComponent.MINUTE, + DatetimeComponent.SECOND, + DatetimeComponent.MILLISECOND, + DatetimeComponent.MICROSECOND, + DatetimeComponent.NANOSECOND, ], ) def test_extract_timestamp_component(timestamp_type, field): col = cudf.Series( ["2010-06-19T13:15:12.1232634", "2011-06-20T13:25:11.2789543"] ).astype(timestamp_type) - expected = getattr(col.dt, field.name.removesuffix("_fraction")) - if field == DatetimeComponent.weekday: + + if field == DatetimeComponent.MILLISECOND: + # millisecond are not exposed directly but included in microseconds: + expected = col.dt.microsecond // 1000 + expected = expected.astype("int16") + elif field == DatetimeComponent.WEEKDAY: # cudf subtracts 1 and that seems to cast: - expected += 1 + expected = col.dt.weekday + 1 expected = expected.astype("int16") - elif field == DatetimeComponent.microsecond_fraction: - # Remove milliseconds from cudf result and cast to int16: - expected = expected % 1000 + elif field == DatetimeComponent.MICROSECOND: + # Remove milliseconds from cudf result: + expected = col.dt.microsecond % 1000 expected = expected.astype("int16") + else: + expected = getattr(col.dt, field.name.lower()) lg_col = LogicalColumn.from_cudf(col._column) res = extract_timestamp_component(lg_col, field)