Timedelta#

class pandas::Timedelta#

pandas C++ class.

Example#

#include <pandas/pandas.h>
using namespace pandas;

// Use Timedelta
Timedelta obj;
// ... operations ...

Constructors#

Signature

Location

Example

explicit Timedelta(int64_t nanoseconds)

pd_timedelta.h:340

View

explicit Timedelta(const std::string& duration_string)

pd_timedelta.h:360

View

Timedelta(int64_t value, const std::string& unit)

pd_timedelta.h:371

View

explicit Timedelta(const numpy::timedelta64& td)

pd_timedelta.h:383

View

explicit Timedelta(const std::chrono::duration<Rep, Period>& dur)

pd_timedelta.h:419

View

Construction#

Signature

Return Type

Location

Example

static Timedelta from_string(const std::string& s) { return Timedelta(s)

static Timedelta

pd_timedelta.h:366

View

static Timedelta from_value(double value, const std::string& unit)

static Timedelta

pd_timedelta.h:378

View

Statistics#

Signature

Return Type

Location

Example

static Timedelta max()

static Timedelta

pd_timedelta.h:438

View

static Timedelta min()

static Timedelta

pd_timedelta.h:434

View

int32_t minutes() const

int32_t

pd_timedelta.h:481

View

Arithmetic#

Signature

Return Type

Location

Example

std::pair<int64_t, Timedelta> divmod(const Timedelta& other) const

std::pair<int64_t, Timedelta>

pd_timedelta.h:996

View

Combining#

Signature

Return Type

Location

Example

static void appendFractionalNanos(std::ostringstream& oss, int64_t frac)

static void

pd_timedelta.h:611

appendFractionalNanos(oss, frac)

pd_timedelta.h:647

appendFractionalNanos(oss, frac)

pd_timedelta.h:679

I/O#

Signature

Return Type

Location

Example

std::chrono::nanoseconds to_chrono() const

std::chrono::nanoseconds

pd_timedelta.h:586

View

Duration to_chrono_duration() const

Duration

pd_timedelta.h:595

View

int64_t to_numpy(const std::string& dtype = "numpy::timedelta64[ns]", bool copy = false) const

int64_t

pd_timedelta.h:579

View

numpy::timedelta64 to_timedelta64(numpy::DateTimeUnit unit = numpy::DateTimeUnit::Nanosecond) const

numpy::timedelta64

pd_timedelta.h:548

View

Other Methods#

Signature

Return Type

Location

Example

static Timedelta NaT()

static Timedelta

pd_timedelta.h:428

View

Timedelta abs() const

Timedelta

pd_timedelta.h:1006

View

Timedelta as_unit(const std::string& unit, bool round_ok = true) const

Timedelta

pd_timedelta.h:828

View

Timedelta ceil(const std::string& freq, const std::string& ambiguous = "raise", const std::string& nonexistent = "raise") const

Timedelta

pd_timedelta.h:775

View

int64_t components_days() const { return days()

int64_t

pd_timedelta.h:512

View

std::string components_str() const

std::string

pd_timedelta.h:738

View

void computeComponents() const

void

pd_timedelta.h:69

int64_t days() const

int64_t

pd_timedelta.h:469

View

int64_t delta() const

int64_t

pd_timedelta.h:464

View

Timedelta floor(const std::string& freq, const std::string& ambiguous = "raise", const std::string& nonexistent = "raise") const

Timedelta

pd_timedelta.h:757

View

int64_t floor_divide(const Timedelta& other) const

int64_t

pd_timedelta.h:980

Timedelta floor_divide(int64_t scalar) const

Timedelta

pd_timedelta.h:988

std::string frac_str(buf)

std::string

pd_timedelta.h:615

int32_t hours() const

int32_t

pd_timedelta.h:475

View

void invalidateCache()

void

pd_timedelta.h:65

bool isNaT() const

bool

pd_timedelta.h:450

View

std::string isoformat() const

std::string

pd_timedelta.h:687

View

int32_t microseconds() const

int32_t

pd_timedelta.h:499

View

int32_t milliseconds() const

int32_t

pd_timedelta.h:493

View

int32_t nanoseconds() const

int32_t

pd_timedelta.h:505

View

static int64_t parseDurationString(const std::string& s)

static int64_t

pd_timedelta.h:165

static int64_t parseFrequencyToNanos(const std::string& freq)

static int64_t

pd_timedelta.h:103

static int64_t parseISO8601Duration(const std::string& input)

static int64_t

pd_timedelta.h:116

static Timedelta resolution()

static Timedelta

pd_timedelta.h:442

View

Timedelta round(const std::string& freq, const std::string& ambiguous = "raise", const std::string& nonexistent = "raise") const

Timedelta

pd_timedelta.h:796

View

std::string s_str(buf)

std::string

pd_timedelta.h:717

View

int32_t seconds() const

int32_t

pd_timedelta.h:487

View

std::istringstream ss(input)

std::istringstream

pd_timedelta.h:237

View

std::string toString() const

std::string

pd_timedelta.h:626

View

double total_days() const

double

pd_timedelta.h:533

View

double total_hours() const

double

pd_timedelta.h:528

View

double total_minutes() const

double

pd_timedelta.h:523

View

double total_nanoseconds() const

double

pd_timedelta.h:538

double total_seconds() const

double

pd_timedelta.h:518

View

int64_t value() const

int64_t

pd_timedelta.h:459

View

Code Examples#

The following examples are extracted from the test suite.

Timedelta (pd_test_5_all.cpp:25576)
25566    apply_default_display(df);
25567    check_str("case_38.datetime_with_nat_site4",
25568              EXPECTED_case_38_datetime_with_nat_site4,
25569              df.to_string(), local_fail);
25570}
25571
25572void f_set_index_col_multiindex_display_10_507319_case_39_timedelta_site3(int& local_fail) {
25573    std::cout << "----- case_39_timedelta_site3 -----\n";
25574    pandas::DataFrame df;
25575    std::vector<pandas::Timedelta> tds = {
25576        pandas::Timedelta("1 days"),
25577        pandas::Timedelta("2 days"),
25578        pandas::Timedelta("-1 days"),
25579        pandas::Timedelta("3 days"),
25580    };
25581    df.add_column<pandas::Timedelta>("td", tds);
25582    df.set_columns_levels({{"G"}, {"td"}}, {"top", "leaf"});
25583    df.set_multiindex(make_mi_ab_short());
25584    apply_default_display(df);
25585    check_str("case_39.timedelta_site3",
25586              EXPECTED_case_39_timedelta_site3,
Timedelta (pd_test_5_all.cpp:25576)
25566    apply_default_display(df);
25567    check_str("case_38.datetime_with_nat_site4",
25568              EXPECTED_case_38_datetime_with_nat_site4,
25569              df.to_string(), local_fail);
25570}
25571
25572void f_set_index_col_multiindex_display_10_507319_case_39_timedelta_site3(int& local_fail) {
25573    std::cout << "----- case_39_timedelta_site3 -----\n";
25574    pandas::DataFrame df;
25575    std::vector<pandas::Timedelta> tds = {
25576        pandas::Timedelta("1 days"),
25577        pandas::Timedelta("2 days"),
25578        pandas::Timedelta("-1 days"),
25579        pandas::Timedelta("3 days"),
25580    };
25581    df.add_column<pandas::Timedelta>("td", tds);
25582    df.set_columns_levels({{"G"}, {"td"}}, {"top", "leaf"});
25583    df.set_multiindex(make_mi_ab_short());
25584    apply_default_display(df);
25585    check_str("case_39.timedelta_site3",
25586              EXPECTED_case_39_timedelta_site3,
Timedelta (pd_test_5_all.cpp:25576)
25566    apply_default_display(df);
25567    check_str("case_38.datetime_with_nat_site4",
25568              EXPECTED_case_38_datetime_with_nat_site4,
25569              df.to_string(), local_fail);
25570}
25571
25572void f_set_index_col_multiindex_display_10_507319_case_39_timedelta_site3(int& local_fail) {
25573    std::cout << "----- case_39_timedelta_site3 -----\n";
25574    pandas::DataFrame df;
25575    std::vector<pandas::Timedelta> tds = {
25576        pandas::Timedelta("1 days"),
25577        pandas::Timedelta("2 days"),
25578        pandas::Timedelta("-1 days"),
25579        pandas::Timedelta("3 days"),
25580    };
25581    df.add_column<pandas::Timedelta>("td", tds);
25582    df.set_columns_levels({{"G"}, {"td"}}, {"top", "leaf"});
25583    df.set_multiindex(make_mi_ab_short());
25584    apply_default_display(df);
25585    check_str("case_39.timedelta_site3",
25586              EXPECTED_case_39_timedelta_site3,
Timedelta (pd_test_5_all.cpp:25576)
25566    apply_default_display(df);
25567    check_str("case_38.datetime_with_nat_site4",
25568              EXPECTED_case_38_datetime_with_nat_site4,
25569              df.to_string(), local_fail);
25570}
25571
25572void f_set_index_col_multiindex_display_10_507319_case_39_timedelta_site3(int& local_fail) {
25573    std::cout << "----- case_39_timedelta_site3 -----\n";
25574    pandas::DataFrame df;
25575    std::vector<pandas::Timedelta> tds = {
25576        pandas::Timedelta("1 days"),
25577        pandas::Timedelta("2 days"),
25578        pandas::Timedelta("-1 days"),
25579        pandas::Timedelta("3 days"),
25580    };
25581    df.add_column<pandas::Timedelta>("td", tds);
25582    df.set_columns_levels({{"G"}, {"td"}}, {"top", "leaf"});
25583    df.set_multiindex(make_mi_ab_short());
25584    apply_default_display(df);
25585    check_str("case_39.timedelta_site3",
25586              EXPECTED_case_39_timedelta_site3,
Timedelta (pd_test_5_all.cpp:25576)
25566    apply_default_display(df);
25567    check_str("case_38.datetime_with_nat_site4",
25568              EXPECTED_case_38_datetime_with_nat_site4,
25569              df.to_string(), local_fail);
25570}
25571
25572void f_set_index_col_multiindex_display_10_507319_case_39_timedelta_site3(int& local_fail) {
25573    std::cout << "----- case_39_timedelta_site3 -----\n";
25574    pandas::DataFrame df;
25575    std::vector<pandas::Timedelta> tds = {
25576        pandas::Timedelta("1 days"),
25577        pandas::Timedelta("2 days"),
25578        pandas::Timedelta("-1 days"),
25579        pandas::Timedelta("3 days"),
25580    };
25581    df.add_column<pandas::Timedelta>("td", tds);
25582    df.set_columns_levels({{"G"}, {"td"}}, {"top", "leaf"});
25583    df.set_multiindex(make_mi_ab_short());
25584    apply_default_display(df);
25585    check_str("case_39.timedelta_site3",
25586              EXPECTED_case_39_timedelta_site3,
from_string (pd_test_3_all.cpp:10837)
10827    const auto& s1 = df.column<int64_t>("A");
10828    const auto& s2 = df.col<int64_t>("A");
10829    if (s1.size() != s2.size() || s1[0] != s2[0]) {
10830        std::cout << "  [FAIL] : in pd_test_3_all_column_alias() : mismatch" << std::endl;
10831        throw std::runtime_error("pd_test_3_all_column_alias failed");
10832    }
10833    std::cout << " -> tests passed" << std::endl;
10834}
10835
10836void pd_test_3_all_timedelta_from_string() {
10837    std::cout << "========= Timedelta::from_string() ======================";
10838    auto td1 = pandas::Timedelta::from_string("1 days");
10839    pandas::Timedelta td2("1 days");
10840    if (td1.value() != td2.value()) {
10841        std::cout << "  [FAIL] : in pd_test_3_all_timedelta_from_string() : mismatch" << std::endl;
10842        throw std::runtime_error("pd_test_3_all_timedelta_from_string failed");
10843    }
10844    std::cout << " -> tests passed" << std::endl;
10845}
10846
10847void pd_test_3_all_replace_int() {
from_value (pd_test_timedelta_scalar.cpp:158)
148        std::cout << "  Timedelta(2, 'W') = " << td_week.days() << " days" << std::endl;
149        if (td_week.days() != 14) {
150            std::cout << "[FAIL] np_test_timedelta_constructors: Timedelta(2, 'W') expected 14 days, got "
151                      << td_week.days() << std::endl;
152            errors++;
153        }
154    }
155
156    // From value and unit - static factory for fractional values
157    {
158        pandas::Timedelta td_frac = pandas::Timedelta::from_value(1.5, "h");  // 1.5 hours = 90 minutes
159        std::cout << "  Timedelta::from_value(1.5, 'h') = " << td_frac.total_minutes() << " minutes" << std::endl;
160        if (std::abs(td_frac.total_minutes() - 90.0) > 0.0001) {
161            std::cout << "[FAIL] np_test_timedelta_constructors: from_value(1.5, 'h') expected 90 minutes, got "
162                      << td_frac.total_minutes() << std::endl;
163            errors++;
164        }
165
166        pandas::Timedelta td_frac2 = pandas::Timedelta::from_value(0.5, "D");  // 0.5 days = 12 hours
167        std::cout << "  Timedelta::from_value(0.5, 'D') = " << td_frac2.total_hours() << " hours" << std::endl;
168        if (std::abs(td_frac2.total_hours() - 12.0) > 0.0001) {
max (pd_test_1_all.cpp:771)
761        pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true);  // ordered
762
763        // Test min
764        std::optional<std::string> min_val = arr.min();
765        if (!min_val.has_value() || *min_val != "low") {
766            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl;
767            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'");
768        }
769
770        // Test max
771        std::optional<std::string> max_val = arr.max();
772        if (!max_val.has_value() || *max_val != "high") {
773            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl;
774            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'");
775        }
776
777        // Test unordered throws for min/max
778        pandas::CategoricalArray unordered = arr.as_unordered();
779        bool threw = false;
780        try {
781            unordered.min();
min (pd_test_1_all.cpp:764)
754    }
755
756    void pd_test_categorical_array_ordered_operations() {
757        std::cout << "========= CategoricalArray: ordered operations (min/max) ======================= ";
758
759        std::vector<std::string> cats = {"low", "medium", "high"};
760        std::vector<numpy::int32> codes = {0, 2, 1, 0, -1};  // low, high, medium, low, NA
761        pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true);  // ordered
762
763        // Test min
764        std::optional<std::string> min_val = arr.min();
765        if (!min_val.has_value() || *min_val != "low") {
766            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl;
767            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'");
768        }
769
770        // Test max
771        std::optional<std::string> max_val = arr.max();
772        if (!max_val.has_value() || *max_val != "high") {
773            std::cout << "  [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl;
774            throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'");
minutes (pd_test_3_all.cpp:21614)
21604    }
21605    if (d.months() != 2) {
21606        throw std::runtime_error("DateOffset: months mismatch");
21607    }
21608    if (d.days() != 5) {
21609        throw std::runtime_error("DateOffset: days mismatch");
21610    }
21611    if (d.hours() != 3) {
21612        throw std::runtime_error("DateOffset: hours mismatch");
21613    }
21614    if (d.minutes() != 30) {
21615        throw std::runtime_error("DateOffset: minutes mismatch");
21616    }
21617    if (d.seconds() != 10) {
21618        throw std::runtime_error("DateOffset: seconds mismatch");
21619    }
21620
21621    std::cout << " -> tests passed" << std::endl;
21622}
21623
21624void test_yearend_freqstr() {
divmod (pd_test_3_all.cpp:12077)
12067    auto cov_val = s1.cov(s2);
12068    if (!cov_val.has_value()) {
12069        std::cout << "  [FAIL] : covariance should have a value" << std::endl;
12070        throw std::runtime_error("pd_test_series_corr_cov failed");
12071    }
12072
12073    std::cout << " -> tests passed" << std::endl;
12074}
12075
12076// ============================================================================
12077// Test 9: divmod()
12078// ============================================================================
12079void pd_test_series_divmod() {
12080    std::cout << "========= Series.divmod() ==========================";
12081
12082    std::vector<double> vals = {10.0, 20.0, 30.0};
12083    pandas::Series<double> s(vals, "test");
12084
12085    auto [quot, rem] = s.divmod(7.0);
12086
12087    // 10/7 = 1 remainder 3
to_chrono (pd_test_timedelta_scalar.cpp:400)
390        int64_t nanos = td.to_numpy();
391        if (nanos != pandas::Timedelta::NANOS_PER_DAY) {
392            std::cout << "[FAIL] np_test_timedelta_conversions: to_numpy expected "
393                      << pandas::Timedelta::NANOS_PER_DAY << ", got " << nanos << std::endl;
394            errors++;
395        }
396    }
397
398    // to_chrono
399    {
400        std::chrono::nanoseconds dur = td.to_chrono();
401        if (dur.count() != pandas::Timedelta::NANOS_PER_DAY) {
402            std::cout << "[FAIL] np_test_timedelta_conversions: to_chrono expected "
403                      << pandas::Timedelta::NANOS_PER_DAY << ", got " << dur.count() << std::endl;
404            errors++;
405        }
406    }
407
408    // to_chrono_duration
409    {
410        auto hrs = td.to_chrono_duration<std::chrono::hours>();
to_chrono_duration (pd_test_timedelta_scalar.cpp:410)
400        std::chrono::nanoseconds dur = td.to_chrono();
401        if (dur.count() != pandas::Timedelta::NANOS_PER_DAY) {
402            std::cout << "[FAIL] np_test_timedelta_conversions: to_chrono expected "
403                      << pandas::Timedelta::NANOS_PER_DAY << ", got " << dur.count() << std::endl;
404            errors++;
405        }
406    }
407
408    // to_chrono_duration
409    {
410        auto hrs = td.to_chrono_duration<std::chrono::hours>();
411        if (hrs.count() != 24) {
412            std::cout << "[FAIL] np_test_timedelta_conversions: to_chrono_duration<hours> expected 24, got "
413                      << hrs.count() << std::endl;
414            errors++;
415        }
416    }
417
418    if (errors == 0) {
419        std::cout << "np_test_timedelta_conversions -> tests passed" << std::endl;
420    }
to_numpy (pd_test_1_all.cpp:16764)
16754        // =====================================================================
16755        // to_numpy Tests
16756        // =====================================================================
16757
16758        void pd_test_ndframe_to_numpy() {
16759            std::cout << "========= to_numpy =============================================" << std::endl;
16760
16761            pandas::Series<int> s({10, 20, 30});
16762
16763            auto arr = s.to_numpy();
16764
16765            bool passed = arr.getSize() == 3;
16766            if (!passed) {
16767                std::cout << "  [FAIL] : in pd_test_ndframe_to_numpy() : size" << std::endl;
16768                throw std::runtime_error("pd_test_ndframe_to_numpy failed: size");
16769            }
16770
16771            passed = arr.getElementAt({0}) == 10 && arr.getElementAt({1}) == 20 && arr.getElementAt({2}) == 30;
16772            if (!passed) {
16773                std::cout << "  [FAIL] : in pd_test_ndframe_to_numpy() : values" << std::endl;
to_timedelta64 (pd_test_timedelta_scalar.cpp:370)
360// =============================================================================
361// Test 5: Conversion Methods
362// =============================================================================
363int np_test_timedelta_conversions() {
364    int errors = 0;
365
366    pandas::Timedelta td(1, 0, 0);  // 1 day
367
368    // to_timedelta64 with Day unit
369    {
370        numpy::timedelta64 td64 = td.to_timedelta64(numpy::DateTimeUnit::Day);
371        if (td64.getValue() != 1) {
372            std::cout << "[FAIL] np_test_timedelta_conversions: to_timedelta64(Day) expected 1, got "
373                      << td64.getValue() << std::endl;
374            errors++;
375        }
376    }
377
378    // to_timedelta64 with Hour unit
379    {
380        numpy::timedelta64 td64 = td.to_timedelta64(numpy::DateTimeUnit::Hour);
NaT (pd_test_1_all.cpp:1305)
1295        pandas::DatetimeArray arr(std::vector<std::string>{
1296            "2023-06-15",
1297            "NaT",
1298            "2023-01-01",
1299            "2023-12-31"
1300        });
1301
1302        // argsort ascending
1303        auto indices = arr.argsort(true, "last");
1304        // Expected order: 2023-01-01(2), 2023-06-15(0), 2023-12-31(3), NaT(1)
1305        if (indices.getElementAt({0}) != 2) {
1306            std::cout << "  [FAIL] : argsort: first should be index 2 (2023-01-01)" << std::endl;
1307            throw std::runtime_error("pd_test_datetime_array_sorting failed: argsort first");
1308        }
1309        if (indices.getElementAt({3}) != 1) {
1310            std::cout << "  [FAIL] : argsort: last should be index 1 (NaT)" << std::endl;
1311            throw std::runtime_error("pd_test_datetime_array_sorting failed: NaT position");
1312        }
1313
1314        // argmin
abs (pd_test_1_all.cpp:283)
273            std::optional<bool>(true)
274        });
275
276        auto s = arr.sum();
277        if (!s.has_value() || s.value() != 3) {
278            std::cout << "  [FAIL] : in pd_test_boolean_array_reductions() : sum should be 3" << std::endl;
279            throw std::runtime_error("pd_test_boolean_array_reductions failed: sum");
280        }
281
282        auto m = arr.mean();
283        if (!m.has_value() || std::abs(m.value() - 0.75) > 0.001) {
284            std::cout << "  [FAIL] : in pd_test_boolean_array_reductions() : mean should be 0.75" << std::endl;
285            throw std::runtime_error("pd_test_boolean_array_reductions failed: mean");
286        }
287
288        std::cout << " -> tests passed" << std::endl;
289    }
290
291    void pd_test_boolean_array_dtype() {
292        std::cout << "========= BooleanArray: dtype ======================= ";
as_unit (pd_test_1_all.cpp:9361)
9351    data.setElementAt({1}, numpy::datetime64(2000000000LL, numpy::DateTimeUnit::Nanosecond));  // 2 seconds in ns
9352
9353    numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
9354    mask.setElementAt({0}, numpy::bool_(false));
9355    mask.setElementAt({1}, numpy::bool_(false));
9356
9357    pandas::DatetimeArray arr(data, mask);
9358    pandas::DatetimeTDMixin idx(arr, "test");
9359
9360    // Convert to microseconds
9361    pandas::DatetimeTDMixin us_idx = idx.as_unit("us");
9362
9363    // Convert to same unit (should return identical)
9364    pandas::DatetimeTDMixin same_idx = idx.as_unit("ns");
9365
9366    bool passed = (us_idx.size() == 2 && same_idx.size() == 2 &&
9367                   us_idx.name().has_value() && *us_idx.name() == "test");
9368    if (!passed) {
9369        std::cout << "  [FAIL] : in pd_test_datetime_as_unit() : as_unit check failed" << std::endl;
9370        throw std::runtime_error("pd_test_datetime_as_unit failed");
9371    }
ceil (pd_test_1_all.cpp:4949)
4939                throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed");
4940            }
4941
4942            auto f = a.floor();
4943            passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001;
4944            if (!passed) {
4945                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl;
4946                throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed");
4947            }
4948
4949            auto c = a.ceil();
4950            passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001;
4951            if (!passed) {
4952                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl;
4953                throw std::runtime_error("pd_test_arithmetic_series_round failed: ceil failed");
4954            }
4955
4956            // Round with decimals
4957            pandas::Series<double> b({1.234, 2.567, 3.891});
4958            auto r2 = b.round(2);
4959            passed = std::abs(r2[0] - 1.23) < 0.001 && std::abs(r2[1] - 2.57) < 0.001;
components_days (pd_test_timedelta_scalar.cpp:282)
272        if (td.nanoseconds() != 300) {
273            std::cout << "[FAIL] np_test_timedelta_components: nanoseconds() expected 300, got "
274                      << td.nanoseconds() << std::endl;
275            errors++;
276        }
277    }
278
279    // Components alias
280    {
281        pandas::Timedelta td(5, 0, 0);
282        if (td.components_days() != 5) {
283            std::cout << "[FAIL] np_test_timedelta_components: components_days() expected 5, got "
284                      << td.components_days() << std::endl;
285            errors++;
286        }
287    }
288
289    if (errors == 0) {
290        std::cout << "np_test_timedelta_components -> tests passed" << std::endl;
291    }
292    return errors;
components_str (pd_test_timedelta_scalar.cpp:476)
466        if (iso.find("P1D") == std::string::npos) {
467            std::cout << "[FAIL] np_test_timedelta_strings: isoformat expected 'P1D...', got '"
468                      << iso << "'" << std::endl;
469            errors++;
470        }
471    }
472
473    // components_str
474    {
475        pandas::Timedelta td(1, 2, 30, 45, 100, 200, 300);
476        std::string comp = td.components_str();
477        if (comp.find("days=1") == std::string::npos) {
478            std::cout << "[FAIL] np_test_timedelta_strings: components_str missing days=1, got '"
479                      << comp << "'" << std::endl;
480            errors++;
481        }
482    }
483
484    if (errors == 0) {
485        std::cout << "np_test_timedelta_strings -> tests passed" << std::endl;
486    }
days (pd_test_1_all.cpp:4160)
4150    void pd_test_timedelta_array_component_days() {
4151        std::cout << "========= TimedeltaArray: days component ======================= ";
4152
4153        pandas::TimedeltaArray arr({
4154            std::optional<numpy::timedelta64>(numpy::timedelta64(3, numpy::DateTimeUnit::Day)),
4155            std::nullopt,
4156            std::optional<numpy::timedelta64>(numpy::timedelta64(36, numpy::DateTimeUnit::Hour))  // 1.5 days
4157        });
4158
4159        auto days_arr = arr.days();
4160
4161        auto d0 = days_arr[0];
4162        if (!d0.has_value() || d0.value() != 3) {
4163            std::cout << "  [FAIL] : days[0] should be 3" << std::endl;
4164            throw std::runtime_error("pd_test_timedelta_array_component_days failed: days[0]");
4165        }
4166
4167        auto d1 = days_arr[1];
4168        if (d1.has_value()) {
4169            std::cout << "  [FAIL] : days[1] should be NA (NaT)" << std::endl;
delta (pd_test_timedelta_scalar.cpp:345)
335    // total_days
336    {
337        double days = td.total_days();
338        if (std::abs(days - 1.5) > 0.0001) {
339            std::cout << "[FAIL] np_test_timedelta_total_conversions: total_days expected 1.5, got "
340                      << days << std::endl;
341            errors++;
342        }
343    }
344
345    // value() and delta()
346    {
347        if (td.value() != td.delta()) {
348            std::cout << "[FAIL] np_test_timedelta_total_conversions: value() != delta()"
349                      << std::endl;
350            errors++;
351        }
352    }
353
354    if (errors == 0) {
355        std::cout << "np_test_timedelta_total_conversions -> tests passed" << std::endl;
floor (pd_test_1_all.cpp:4942)
4932            pandas::Series<double> a({1.4, 2.5, 3.6, -1.4, -2.5});
4933
4934            auto r = a.round();
4935            bool passed = std::abs(r[0] - 1.0) < 0.001 && std::abs(r[2] - 4.0) < 0.001;
4936            if (!passed) {
4937                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : round failed" << std::endl;
4938                throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed");
4939            }
4940
4941            auto f = a.floor();
4942            passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001;
4943            if (!passed) {
4944                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl;
4945                throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed");
4946            }
4947
4948            auto c = a.ceil();
4949            passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001;
4950            if (!passed) {
4951                std::cout << "  [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl;
hours (pd_test_1_all.cpp:9567)
9557        std::cout << std::endl << "  [FAIL] : floor result incorrect";
9558        passed = false;
9559    }
9560
9561    // ceil should give 2 hours
9562    if (ceiled.total_seconds() != 7200.0) {
9563        std::cout << std::endl << "  [FAIL] : ceil result incorrect";
9564        passed = false;
9565    }
9566
9567    // round should give 2 hours (30m45s > 30m)
9568    if (rounded.total_seconds() != 7200.0) {
9569        std::cout << std::endl << "  [FAIL] : round result incorrect";
9570        passed = false;
9571    }
9572
9573    if (!passed) {
9574        throw std::runtime_error("pd_test_timedelta_rounding_params failed");
9575    }
9576
9577    std::cout << " -> tests passed" << std::endl;
isNaT (pd_test_3_all.cpp:1523)
1513    }
1514
1515    // Case B: pandas::Timedelta == pandas::Timedelta
1516    {
1517        static_assert(std::is_same_v<pandas::Timedelta, pandas::Timedelta>,
1518                      "pandas::Timedelta must alias pandas::Timedelta");
1519    }
1520
1521    // Case C: pandas::NaT is a NaT-valued Timestamp
1522    {
1523        if (!pandas::NaT.isNaT()) {
1524            throw std::runtime_error("pandas::NaT is not a NaT value");
1525        }
1526        pandas::Timestamp default_ts;
1527        if (default_ts.isNaT() != pandas::NaT.isNaT()) {
1528            throw std::runtime_error(
1529                "pandas::NaT and default Timestamp NaT-state mismatch");
1530        }
1531    }
1532
1533    // Case D: round-trip - reproduces the failing test pattern
isoformat (pd_test_timedelta_scalar.cpp:465)
455        if (nat.toString() != "NaT") {
456            std::cout << "[FAIL] np_test_timedelta_strings: toString(NaT) expected 'NaT', got '"
457                      << nat.toString() << "'" << std::endl;
458            errors++;
459        }
460    }
461
462    // isoformat
463    {
464        pandas::Timedelta td(1, 2, 30);
465        std::string iso = td.isoformat();
466        if (iso.find("P1D") == std::string::npos) {
467            std::cout << "[FAIL] np_test_timedelta_strings: isoformat expected 'P1D...', got '"
468                      << iso << "'" << std::endl;
469            errors++;
470        }
471    }
472
473    // components_str
474    {
475        pandas::Timedelta td(1, 2, 30, 45, 100, 200, 300);
microseconds (pd_test_1_all.cpp:19701)
19691    constexpr int64_t NS_PER_US = 1000LL;
19692    std::vector<std::optional<numpy::timedelta64>> values = {
19693        make_td(0),                        // 0 us
19694        make_td(500 * NS_PER_US),          // 500 us
19695        make_td(NS_PER_SEC + 100 * NS_PER_US)  // 1 sec + 100 us
19696    };
19697    pandas::TimedeltaArray arr(values);
19698    pandas::TimedeltaIndex idx(arr);
19699
19700    auto microseconds = idx.microseconds();
19701
19702    bool passed = (microseconds.size() == 3);
19703    if (!passed) {
19704        std::cout << "  [FAIL] : in pd_test_timedelta_index_microseconds()" << std::endl;
19705        throw std::runtime_error("pd_test_timedelta_index_microseconds failed");
19706    }
19707
19708    std::cout << " -> tests passed" << std::endl;
19709}
milliseconds (pd_test_2_all.cpp:10201)
10191#include <Windows.h>
10192#endif
10193
10194namespace dataframe_tests {
10195    namespace dataframe_tests_to_clipboard {
10196
10197        // Helper function to get clipboard content (Windows only)
10198#ifdef _WIN32
10199        std::string get_clipboard_text() {
10200            // Add small delay to allow clipboard to stabilize
10201            std::this_thread::sleep_for(std::chrono::milliseconds(5));
10202
10203            if (!OpenClipboard(nullptr)) {
10204                return "";
10205            }
10206
10207            HANDLE hData = GetClipboardData(CF_TEXT);
10208            if (hData == nullptr) {
10209                CloseClipboard();
10210                return "";
10211            }
nanoseconds (pd_test_1_all.cpp:9379)
9369        std::cout << "  [FAIL] : in pd_test_datetime_as_unit() : as_unit check failed" << std::endl;
9370        throw std::runtime_error("pd_test_datetime_as_unit failed");
9371    }
9372
9373    std::cout << " -> tests passed" << std::endl;
9374}
9375
9376void pd_test_timedelta_as_unit() {
9377    std::cout << "========= TimedeltaTDMixin as_unit =========================";
9378
9379    // Create index in nanoseconds (1 hour, 2 hours)
9380    numpy::NDArray<numpy::timedelta64> data(std::vector<size_t>{2});
9381    data.setElementAt({0}, numpy::timedelta64(3600000000000LL, numpy::DateTimeUnit::Nanosecond));   // 1 hour
9382    data.setElementAt({1}, numpy::timedelta64(7200000000000LL, numpy::DateTimeUnit::Nanosecond));   // 2 hours
9383
9384    numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
9385    mask.setElementAt({0}, numpy::bool_(false));
9386    mask.setElementAt({1}, numpy::bool_(false));
9387
9388    pandas::TimedeltaArray arr(data, mask);
9389    pandas::TimedeltaTDMixin idx(arr, "durations");
resolution (pd_test_1_all.cpp:15536)
15526    }
15527
15528    std::cout << " -> tests passed" << std::endl;
15529}
15530
15531// ============================================================================
15532// Resolution Tests
15533// ============================================================================
15534
15535void pd_test_datetime_index_resolution() {
15536    std::cout << "========= DatetimeIndex resolution() =========================";
15537
15538    numpy::NDArray<numpy::datetime64> data(std::vector<size_t>{1});
15539    data.setElementAt({0}, numpy::datetime64(1000LL, numpy::DateTimeUnit::Nanosecond));
15540
15541    numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{1});
15542    mask.setElementAt({0}, numpy::bool_(false));
15543
15544    pandas::DatetimeArray arr(data, mask);
15545    pandas::DatetimeIndexBase idx(arr);
round (pd_test_1_all.cpp:1688)
1678    void pd_test_floating_array_rounding() {
1679        std::cout << "========= FloatingArray: rounding ======================= ";
1680
1681        pandas::FloatingArray<double> arr({
1682            std::optional<double>(1.234),
1683            std::optional<double>(2.567),
1684            std::nullopt
1685        });
1686
1687        auto rounded = arr.round(2);
1688        if (std::abs(rounded[0].value() - 1.23) > 0.001 ||
1689            std::abs(rounded[1].value() - 2.57) > 0.001) {
1690            std::cout << "  [FAIL] : in pd_test_floating_array_rounding() : round(2)" << std::endl;
1691            throw std::runtime_error("pd_test_floating_array_rounding failed: round(2)");
1692        }
1693
1694        if (!rounded.is_na(2)) {
1695            std::cout << "  [FAIL] : in pd_test_floating_array_rounding() : round should preserve NA" << std::endl;
1696            throw std::runtime_error("pd_test_floating_array_rounding failed: NA preservation");
1697        }
s_str (pd_test_5_all.cpp:83216)
83206}
83207
83208void case_7_type_mismatch_add(int& local_fail) {
83209    std::cout << "----- case_7_type_mismatch_add -----\n";
83210
83211    auto invoke = []() {
83212        // String -> "datetime64[ns, UTC]" routes through the
83213        // non-floating-point branch of astype's tz-datetime handling,
83214        // which throws pandas::TypeError via
83215        // error_messages::cannot_astype_convert (pd_series.h:7042).
83216        pandas::Series<std::string> s_str({"a", "b", "c"});
83217        (void)s_str.astype(std::string("datetime64[ns, UTC]"));
83218    };
83219
83220    bool caught_typed = false;
83221    bool caught_other = false;
83222    std::string other_what;
83223    try { invoke(); }
83224    catch (const pandas::TypeError&) { caught_typed = true; }
83225    catch (const std::exception& e) { caught_other = true; other_what = e.what(); }
seconds (pd_test_1_all.cpp:4192)
4182    void pd_test_timedelta_array_component_seconds() {
4183        std::cout << "========= TimedeltaArray: seconds component ======================= ";
4184
4185        pandas::TimedeltaArray arr({
4186            std::optional<numpy::timedelta64>(numpy::timedelta64(90, numpy::DateTimeUnit::Second)),  // 90 secs
4187            std::optional<numpy::timedelta64>(numpy::timedelta64(3700, numpy::DateTimeUnit::Second)), // 1h + 100s
4188            std::nullopt
4189        });
4190
4191        auto secs = arr.seconds();
4192
4193        auto s0 = secs[0];
4194        if (!s0.has_value() || s0.value() != 90) {
4195            std::cout << "  [FAIL] : seconds[0] should be 90" << std::endl;
4196            throw std::runtime_error("pd_test_timedelta_array_component_seconds failed: seconds[0]");
4197        }
4198
4199        auto s1 = secs[1];
4200        if (!s1.has_value() || s1.value() != 3700) {
4201            std::cout << "  [FAIL] : seconds[1] should be 3700" << std::endl;
ss (pd_test_3_all.cpp:27670)
27660            fail++;
27661        } else {
27662            auto cats = str_s->get_cat_categories();
27663            if (cats.size() != 3) {
27664                std::cout << "    FAIL: expected 3 categories, got " << cats.size() << std::endl;
27665                fail++;
27666            }
27667        }
27668    }
27669
27670    pandas::Series<std::string> ss({"a", "b", "a", "c"}, "strs");
27671    auto result2 = ss.astype("category");
27672    auto* str_s2 = dynamic_cast<pandas::Series<std::string>*>(result2.get());
27673    if (!str_s2) {
27674        std::cout << "    FAIL: expected Series<string> for string->category" << std::endl;
27675        fail++;
27676    } else {
27677        if (str_s2->dtype_name() != "category") {
27678            std::cout << "    FAIL: dtype should be category" << std::endl;
27679            fail++;
27680        }
toString (pd_test_1_all.cpp:9539)
9529void pd_test_timedelta_rounding_params() {
9530    std::cout << "========= Timedelta rounding with DST params =====";
9531
9532    // Create a Timedelta: 1h 30m 45s
9533    // Constructor is: (days, hours, minutes, seconds, ...)
9534    pandas::Timedelta td(0, 1, 30, 45);  // 0 days, 1h, 30m, 45s
9535
9536    // Test floor with ambiguous/nonexistent params
9537    pandas::Timedelta floored = td.floor("h", "raise", "raise");
9538    std::cout << std::endl << "  floor('h'): " << floored.toString();
9539
9540    // Test ceil with ambiguous/nonexistent params
9541    pandas::Timedelta ceiled = td.ceil("h", "raise", "raise");
9542    std::cout << std::endl << "  ceil('h'): " << ceiled.toString();
9543
9544    // Test round with ambiguous/nonexistent params
9545    pandas::Timedelta rounded = td.round("h", "raise", "raise");
9546    std::cout << std::endl << "  round('h'): " << rounded.toString();
9547
9548    // Verify results:
total_days (pd_test_timedelta_scalar.cpp:337)
327        double hrs = td.total_hours();
328        if (std::abs(hrs - 36.0) > 0.0001) {
329            std::cout << "[FAIL] np_test_timedelta_total_conversions: total_hours expected 36, got "
330                      << hrs << std::endl;
331            errors++;
332        }
333    }
334
335    // total_days
336    {
337        double days = td.total_days();
338        if (std::abs(days - 1.5) > 0.0001) {
339            std::cout << "[FAIL] np_test_timedelta_total_conversions: total_days expected 1.5, got "
340                      << days << std::endl;
341            errors++;
342        }
343    }
344
345    // value() and delta()
346    {
347        if (td.value() != td.delta()) {
total_hours (pd_test_timedelta_scalar.cpp:69)
59                      << "got days=" << td.days() << " hours=" << td.hours()
60                      << " minutes=" << td.minutes() << std::endl;
61            errors++;
62        }
63    }
64
65    // From timedelta64
66    {
67        numpy::timedelta64 td64(3600, numpy::DateTimeUnit::Second);  // 1 hour
68        pandas::Timedelta td(td64);
69        if (std::abs(td.total_hours() - 1.0) > 0.0001) {
70            std::cout << "[FAIL] np_test_timedelta_constructors: from timedelta64 expected 1 hour, got "
71                      << td.total_hours() << std::endl;
72            errors++;
73        }
74    }
75
76    // From std::chrono::duration
77    {
78        std::chrono::hours h(2);
79        pandas::Timedelta td(h);
total_minutes (pd_test_timedelta_scalar.cpp:106)
 96        pandas::Timedelta td_days(3, "D");  // 3 days
 97        std::cout << "  Timedelta(3, 'D') = " << td_days.days() << " days" << std::endl;
 98        if (td_days.days() != 3) {
 99            std::cout << "[FAIL] np_test_timedelta_constructors: Timedelta(3, 'D') expected 3 days, got "
100                      << td_days.days() << std::endl;
101            errors++;
102        }
103
104        pandas::Timedelta td_min(90, "min");  // 90 minutes = 1.5 hours
105        std::cout << "  Timedelta(90, 'min') = " << td_min.total_minutes() << " minutes" << std::endl;
106        if (std::abs(td_min.total_minutes() - 90.0) > 0.0001) {
107            std::cout << "[FAIL] np_test_timedelta_constructors: Timedelta(90, 'min') expected 90 minutes, got "
108                      << td_min.total_minutes() << std::endl;
109            errors++;
110        }
111
112        pandas::Timedelta td_sec(30, "s");  // 30 seconds
113        std::cout << "  Timedelta(30, 's') = " << td_sec.total_seconds() << " seconds" << std::endl;
114        if (std::abs(td_sec.total_seconds() - 30.0) > 0.0001) {
115            std::cout << "[FAIL] np_test_timedelta_constructors: Timedelta(30, 's') expected 30 seconds, got "
total_seconds (pd_test_1_all.cpp:4224)
4214    void pd_test_timedelta_array_total_seconds() {
4215        std::cout << "========= TimedeltaArray: total_seconds ======================= ";
4216
4217        pandas::TimedeltaArray arr({
4218            std::optional<numpy::timedelta64>(numpy::timedelta64(1, numpy::DateTimeUnit::Day)),
4219            std::optional<numpy::timedelta64>(numpy::timedelta64(1, numpy::DateTimeUnit::Hour)),
4220            std::nullopt
4221        });
4222
4223        auto total = arr.total_seconds();
4224
4225        auto t0 = total[0];
4226        if (!t0.has_value() || std::abs(t0.value() - 86400.0) > 0.001) {
4227            std::cout << "  [FAIL] : total_seconds[0] should be 86400" << std::endl;
4228            throw std::runtime_error("pd_test_timedelta_array_total_seconds failed: total_seconds[0]");
4229        }
4230
4231        auto t1 = total[1];
4232        if (!t1.has_value() || std::abs(t1.value() - 3600.0) > 0.001) {
4233            std::cout << "  [FAIL] : total_seconds[1] should be 3600" << std::endl;
value (pd_test_1_all.cpp:88)
78        // T & T = T, T & F = F, T & NA = NA
79        // F & T = F, F & F = F, F & NA = F (False dominates)
80        // NA & T = NA, NA & F = F, NA & NA = NA
81
82        pandas::BooleanArray t({std::optional<bool>(true)});
83        pandas::BooleanArray f({std::optional<bool>(false)});
84        pandas::BooleanArray na({std::nullopt});
85
86        // T & T = T
87        auto tt = (t & t);
88        if (!tt[0].has_value() || !tt[0].value()) {
89            std::cout << "  [FAIL] : in pd_test_boolean_array_kleene_and() : T & T should be T" << std::endl;
90            throw std::runtime_error("pd_test_boolean_array_kleene_and failed: T & T");
91        }
92
93        // T & F = F
94        auto tf = (t & f);
95        if (!tf[0].has_value() || tf[0].value()) {
96            std::cout << "  [FAIL] : in pd_test_boolean_array_kleene_and() : T & F should be F" << std::endl;
97            throw std::runtime_error("pd_test_boolean_array_kleene_and failed: T & F");
98        }