DatetimeIndexOpsMixin#

class numpy::DatetimeIndexOpsMixin#

numpy C++ class.

Example#

#include <numpy/np_ndarray.h>
using namespace numpy;

// Use DatetimeIndexOpsMixin
DatetimeIndexOpsMixin obj;
// ... operations ...

Constructors#

Signature

Location

Example

explicit DatetimeIndexOpsMixin(const ArrayType& array, const std::optional<std::string>& name = std::nullopt, bool copy = false)

df_datetime_index_ops_mixin.h:138

explicit DatetimeIndexOpsMixin(ArrayType&& array, const std::optional<std::string>& name = std::nullopt)

df_datetime_index_ops_mixin.h:148

DatetimeIndexOpsMixin(const DatetimeIndexOpsMixin& other)

df_datetime_index_ops_mixin.h:157

DatetimeIndexOpsMixin(DatetimeIndexOpsMixin&& other) noexcept

df_datetime_index_ops_mixin.h:165

Statistics#

Signature

Return Type

Location

Example

std::optional<value_type> mean() const

std::optional<value_type>

df_datetime_index_ops_mixin.h:1299

View

IntegerArray<numpy::int32> minute() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:666

View

IntegerArray<numpy::int32> nanosecond() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:727

View

Math Operations#

Signature

Return Type

Location

Example

DatetimeIndexOpsMixin ceil(const std::string& freq) const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:353

View

ArrayType ceiled(result)

ArrayType

df_datetime_index_ops_mixin.h:382

DatetimeIndexOpsMixin floor(const std::string& freq) const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:309

View

ArrayType floored(result)

ArrayType

df_datetime_index_ops_mixin.h:338

DatetimeIndexOpsMixin round(const std::string& freq) const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:267

View

ArrayType rounded(result)

ArrayType

df_datetime_index_ops_mixin.h:294

Linear Algebra#

Signature

Return Type

Location

Example

DatetimeIndexOpsMixin normalize() const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:1151

View

I/O#

Signature

Return Type

Location

Example

PeriodArray to_period(const std::string& freq) const

PeriodArray

df_datetime_index_ops_mixin.h:1259

std::string to_string() const override

std::string

df_datetime_index_ops_mixin.h:1347

View

DatetimeArray to_timestamp(const std::string& how = "start") const

DatetimeArray

df_datetime_index_ops_mixin.h:1245

Type Handling#

Signature

Return Type

Location

Example

DatetimeIndexOpsMixin copy() const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:1401

View

Type Checking#

Signature

Return Type

Location

Example

BooleanArray is_leap_year() const

BooleanArray

df_datetime_index_ops_mixin.h:1090

View

BooleanArray is_month_end() const

BooleanArray

df_datetime_index_ops_mixin.h:936

View

BooleanArray is_month_start() const

BooleanArray

df_datetime_index_ops_mixin.h:908

View

BooleanArray is_negative() const

BooleanArray

df_datetime_index_ops_mixin.h:1120

BooleanArray is_positive() const

BooleanArray

df_datetime_index_ops_mixin.h:1108

BooleanArray is_quarter_end() const

BooleanArray

df_datetime_index_ops_mixin.h:998

View

BooleanArray is_quarter_start() const

BooleanArray

df_datetime_index_ops_mixin.h:966

View

BooleanArray is_year_end() const

BooleanArray

df_datetime_index_ops_mixin.h:1061

View

BooleanArray is_year_start() const

BooleanArray

df_datetime_index_ops_mixin.h:1032

View

BooleanArray is_zero() const

BooleanArray

df_datetime_index_ops_mixin.h:1132

View

Other Methods#

Signature

Return Type

Location

Example

DatetimeIndexOpsMixin asfreq(const std::string& freq, const std::string& how = "start") const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:1226

std::unique_ptr<IndexBase> clone() const override

std::unique_ptr<IndexBase>

df_datetime_index_ops_mixin.h:1340

View

static int64_t datetime_to_period_ordinal(int64_t ns, const std::string& freq)

static int64_t

df_datetime_index_ops_mixin.h:1522

IntegerArray<numpy::int32> day() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:640

View

std::vector<std::string> day_name() const

std::vector<std::string>

df_datetime_index_ops_mixin.h:579

View

IntegerArray<numpy::int32> dayofweek() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:758

View

IntegerArray<numpy::int32> dayofyear() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:777

View

static std::string format_datetime_strftime(const numpy::datetime64& val, const std::string& format)

static std::string

df_datetime_index_ops_mixin.h:1452

static std::string format_period_strftime(numpy::int64 ordinal, const std::string& format, PeriodFrequency freq)

static std::string

df_datetime_index_ops_mixin.h:1478

std::optional<std::string> freq() const

std::optional<std::string>

df_datetime_index_ops_mixin.h:203

std::string freqstr() const

std::string

df_datetime_index_ops_mixin.h:219

gmtime_r(&secs, &tm_time)

df_datetime_index_ops_mixin.h:1467

gmtime_s(&tm_time, &secs)

df_datetime_index_ops_mixin.h:1465

IntegerArray<numpy::int32> hour() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:652

View

std::optional<std::string> inferred_freq() const

std::optional<std::string>

df_datetime_index_ops_mixin.h:232

IntegerArray<numpy::int32> microsecond() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:694

View

\* Floors all datetime values to midnight (00:00:00).

* Floors all datetime values to

df_datetime_index_ops_mixin.h:1147

IntegerArray<numpy::int32> month() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:628

View

std::vector<std::string> month_name() const

std::vector<std::string>

df_datetime_index_ops_mixin.h:541

View

\* Returns the full month names (e.g., "January", "February", ...).

* Returns the full month

df_datetime_index_ops_mixin.h:536

View

\* Returns the full day names (e.g., "Monday", "Tuesday", ...).

* Returns the full day

df_datetime_index_ops_mixin.h:574

View

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

static int64_t

df_datetime_index_ops_mixin.h:1427

static int64_t period_ordinal_to_nanoseconds(numpy::int64 ordinal, PeriodFrequency freq)

static int64_t

df_datetime_index_ops_mixin.h:1493

IntegerArray<numpy::int32> quarter() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:789

View

DatetimeIndexOpsMixin rename(const std::optional<std::string>& new_name) const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:1408

DatetimeIndexOpsMixin result(\*this)

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:1409

View

IntegerArray<numpy::int32> second() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:680

View

void set_freq(const std::optional<std::string>& freq)

void

df_datetime_index_ops_mixin.h:251

DatetimeIndexOpsMixin shift(int64_t periods, const std::optional<std::string>& freq = std::nullopt) const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:415

View

ArrayType shifted(result)

ArrayType

df_datetime_index_ops_mixin.h:447

ArrayType shifted(result)

ArrayType

df_datetime_index_ops_mixin.h:469

DatetimeIndexOpsMixin snap(const std::string& freq = "S") const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:397

std::vector<std::string> strftime(const std::string& date_format) const

std::vector<std::string>

df_datetime_index_ops_mixin.h:493

View

IntegerArray<numpy::int64> td_days() const

IntegerArray<numpy::int64>

df_datetime_index_ops_mixin.h:844

IntegerArray<numpy::int64> td_microseconds() const

IntegerArray<numpy::int64>

df_datetime_index_ops_mixin.h:868

IntegerArray<numpy::int64> td_nanoseconds() const

IntegerArray<numpy::int64>

df_datetime_index_ops_mixin.h:880

IntegerArray<numpy::int64> td_seconds() const

IntegerArray<numpy::int64>

df_datetime_index_ops_mixin.h:856

FloatingArray<double> total_seconds() const

FloatingArray<double>

df_datetime_index_ops_mixin.h:892

View

std::string tz() const

std::string

df_datetime_index_ops_mixin.h:1194

View

bool tz_aware() const

bool

df_datetime_index_ops_mixin.h:1207

DatetimeIndexOpsMixin tz_convert(const std::string& tz) const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:1181

View

DatetimeIndexOpsMixin tz_localize(const std::string& tz) const

DatetimeIndexOpsMixin

df_datetime_index_ops_mixin.h:1166

View

IntegerArray<numpy::int32> week() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:801

View

IntegerArray<numpy::int32> weekday() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:769

View

IntegerArray<numpy::int32> weekofyear() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:832

IntegerArray<numpy::int32> year() const

IntegerArray<numpy::int32>

df_datetime_index_ops_mixin.h:616

View

Code Examples#

The following examples are extracted from the test suite.

mean (np_test_1_all.cpp:11714)
11704    // Create test array
11705    auto array = createInt32Array({ 2, 3 }, 0);
11706    array.setElementAt({ 0, 0 }, 1);
11707    array.setElementAt({ 0, 1 }, 2);
11708    array.setElementAt({ 0, 2 }, 3);
11709    array.setElementAt({ 1, 0 }, 4);
11710    array.setElementAt({ 1, 1 }, 5);
11711    array.setElementAt({ 1, 2 }, 6);
11712
11713    // Test mean without axis
11714    auto mean_all = mean(array);
11715    if (!(approx_equal(mean_all.getElementAt({ 0 }), 3.5, 1e-10))) {
11716        std::string description = std::string("testBasicStatistics():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(mean_all.getElementAt({ 0 }), 3.5, 1e-10))";
11717        std::cout << std::string("[FAIL] ") + description << std::endl;
11718        throw std::runtime_error(description);
11719    }
11720    // std::cout << "[OK] mean (all elements) works correctly\n";
11721
11722    // Test mean along axis 0
11723    auto mean_axis0 = mean(array, 0);
11724    if (!(mean_axis0.getShape()[0] == 3)) {
minute (np_test_5_all.cpp:22186)
22176            errors++;
22177        }
22178
22179        numpy::Timedelta td3("45s");
22180        if (std::abs(td3.total_seconds() - 45.0) > 0.0001) {
22181            std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec"
22182                      << std::endl;
22183            errors++;
22184        }
22185
22186        numpy::Timedelta td4("NaT");
22187        if (!td4.isNaT()) {
22188            std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT"
22189                      << std::endl;
22190            errors++;
22191        }
22192    }
22193
22194    // Stream operator
22195    {
22196        numpy::Timedelta td(1, 2, 30);
nanosecond (np_test_5_all.cpp:22193)
22183            errors++;
22184        }
22185
22186        numpy::Timedelta td4("NaT");
22187        if (!td4.isNaT()) {
22188            std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT"
22189                      << std::endl;
22190            errors++;
22191        }
22192    }
22193
22194    // Stream operator
22195    {
22196        numpy::Timedelta td(1, 2, 30);
22197        std::ostringstream oss;
22198        oss << td;
22199        std::string str = oss.str();
22200        if (str.empty() || str.find("days") == std::string::npos) {
22201            std::cout << "[FAIL] np_test_timedelta_edge_cases: stream operator failed"
22202                      << std::endl;
22203            errors++;
ceil (np_test_2_all.cpp:5735)
5725          throw std::runtime_error(description);
5726      }
5727      if (!(approx_equal(floor_result.getElementAt({ 5 }), std::floor(2.7)))) {
5728          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(floor_result.getElementAt({ 5 }), std::floor(2.7)))";
5729          std::cout << std::string("[FAIL] ") + description << std::endl;
5730          throw std::runtime_error(description);
5731      }
5732      // std::cout << "[OK] floor function works correctly\n";
5733
5734      // Test ceil
5735      auto ceil_result = ceil(values);
5736      if (!(approx_equal(ceil_result.getElementAt({ 0 }), std::ceil(-2.7)))) {
5737          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(ceil_result.getElementAt({ 0 }), std::ceil(-2.7)))";
5738          std::cout << std::string("[FAIL] ") + description << std::endl;
5739          throw std::runtime_error(description);
5740      }
5741      if (!(approx_equal(ceil_result.getElementAt({ 5 }), std::ceil(2.7)))) {
5742          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(ceil_result.getElementAt({ 5 }), std::ceil(2.7)))";
5743          std::cout << std::string("[FAIL] ") + description << std::endl;
5744          throw std::runtime_error(description);
5745      }
floor (np_test_2_all.cpp:5721)
5711          throw std::runtime_error(description);
5712      }
5713      if (!(approx_equal(round_result.getElementAt({ 5 }), std::round(2.7)))) {
5714          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(round_result.getElementAt({ 5 }), std::round(2.7)))";
5715          std::cout << std::string("[FAIL] ") + description << std::endl;
5716          throw std::runtime_error(description);
5717      }
5718      // std::cout << "[OK] round function works correctly\n";
5719
5720      // Test floor
5721      auto floor_result = floor(values);
5722      if (!(approx_equal(floor_result.getElementAt({ 0 }), std::floor(-2.7)))) {
5723          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(floor_result.getElementAt({ 0 }), std::floor(-2.7)))";
5724          std::cout << std::string("[FAIL] ") + description << std::endl;
5725          throw std::runtime_error(description);
5726      }
5727      if (!(approx_equal(floor_result.getElementAt({ 5 }), std::floor(2.7)))) {
5728          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(floor_result.getElementAt({ 5 }), std::floor(2.7)))";
5729          std::cout << std::string("[FAIL] ") + description << std::endl;
5730          throw std::runtime_error(description);
5731      }
round (np_test_1_all.cpp:23769)
23759          throw std::runtime_error(description);
23760      }
23761      if (!(power_scalar_result.getShape() == array.getShape())) {
23762          std::string description = std::string("testMathFunctionSignatures():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(power_scalar_result.getShape() == array.getShape())";
23763          std::cout << std::string("[FAIL] ") + description << std::endl;
23764          throw std::runtime_error(description);
23765      }
23766      // std::cout << "[OK] Power functions have correct signatures\n";
23767
23768      // Test rounding functions with new decimals parameter
23769      auto round_result = round(array);        // Default decimals=0
23770      auto round_decimals_result = round(array, 2);  // With decimals
23771      if (!(round_result.getShape() == array.getShape())) {
23772          std::string description = std::string("testMathFunctionSignatures():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(round_result.getShape() == array.getShape())";
23773          std::cout << std::string("[FAIL] ") + description << std::endl;
23774          throw std::runtime_error(description);
23775      }
23776      if (!(round_decimals_result.getShape() == array.getShape())) {
23777          std::string description = std::string("testMathFunctionSignatures():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(round_decimals_result.getShape() == array.getShape())";
23778          std::cout << std::string("[FAIL] ") + description << std::endl;
23779          throw std::runtime_error(description);
normalize (np_test_5_all.cpp:22817)
22807      if (str.find("2024") == std::string::npos) { pass = false; fail_msg = "toString should contain year"; }
22808
22809      // isoformat
22810      std::string iso = ts.isoformat();
22811      if (iso.find("2024-06-15") == std::string::npos) { pass = false; fail_msg = "isoformat should contain date"; }
22812
22813      // isoformat with space separator
22814      std::string iso_space = ts.isoformat(' ');
22815      if (iso_space.find(" ") == std::string::npos) { pass = false; fail_msg = "isoformat with space separator"; }
22816
22817      // strftime
22818      std::string fmt = ts.strftime("%Y/%m/%d");
22819      if (fmt != "2024/06/15") { pass = false; fail_msg = "strftime format"; }
22820
22821      // ctime
22822      std::string ct = ts.ctime();
22823      if (ct.find("2024") == std::string::npos) { pass = false; fail_msg = "ctime should contain year"; }
22824
22825      // day_name
22826      std::string dayname = ts.day_name();
22827      if (dayname != "Saturday") { pass = false; fail_msg = "2024-06-15 is Saturday"; }
to_string (np_test_1_all.cpp:454)
444    // Modify through different views
445    view1.setElementAt({0, 0}, 100);
446    view2.setElementAt({2, 1}, 200);  // This is (1, 2) in original
447    view3.setElementAt({0, 0}, 300);  // This is (1, 1) in original
448
449    // std::cout << "After modifications through multiple views:" << std::endl;
450    //original.printArray();
451
452    // Verify all changes are reflected
453    if (!(original.getElementAt({0, 0}) == 100)) {
454        std::string description = std::string("testAdvancedViewLifecycle():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(original.getElementAt({0, 0}) == 100)";
455        std::cout << std::string("[FAIL] ") + description << std::endl;
456        throw std::runtime_error(description);
457    }
458    if (!(original.getElementAt({1, 2}) == 200)) {
459        std::string description = std::string("testAdvancedViewLifecycle():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(original.getElementAt({1, 2}) == 200)";
460        std::cout << std::string("[FAIL] ") + description << std::endl;
461        throw std::runtime_error(description);
462    }
463    if (!(original.getElementAt({1, 1}) == 300)) {
464        std::string description = std::string("testAdvancedViewLifecycle():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(original.getElementAt({1, 1}) == 300)";
copy (np_test_1_all.cpp:9812)
9802    //original.printArray();
9803
9804    // The modification should be at position (1,1) in original
9805    if (!(original.getElementAt({1, 1}) == 9999)) {
9806        std::string description = std::string("testSliceCopyVsViewMemoryOwnership():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(original.getElementAt({1, 1}) == 9999)";
9807        std::cout << std::string("[FAIL] ") + description << std::endl;
9808        throw std::runtime_error(description);
9809    }
9810    // std::cout << "[OK] Slice view shares memory with original";
9811
9812    // Test slice copy (should be independent)
9813    auto slice_copy = original.sliceArray({{2, 4}, {2, 4}});
9814    // std::cout << "Slice copy [2:4, 2:4]:";
9815    //slice_copy.printArray();
9816
9817    slice_copy.setElementAt({0, 0}, 7777);
9818
9819    // std::cout << "After modifying slice copy at (0,0):" << std::endl;
9820    // std::cout << "Original array:" << std::endl;
9821    //original.printArray();
9822    // std::cout << "Slice copy:" << std::endl;
is_leap_year (np_test_5_all.cpp:22577)
22567        numpy::Timestamp::strptime("", "%Y-%m-%d");
22568      } catch (const std::invalid_argument&) {
22569        threw = true;
22570      }
22571      if (!threw) {
22572        throw std::runtime_error("strptime failed: should throw for empty string");
22573      }
22574
22575      // Test 9: Empty format should throw
22576      threw = false;
22577      try {
22578        numpy::Timestamp::strptime("2024-03-15", "");
22579      } catch (const std::invalid_argument&) {
22580        threw = true;
22581      }
22582      if (!threw) {
22583        throw std::runtime_error("strptime failed: should throw for empty format");
22584      }
22585
22586      // Test 10: Literal percent
22587      numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d");
is_month_end (np_test_5_all.cpp:22590)
22580        threw = true;
22581      }
22582      if (!threw) {
22583        throw std::runtime_error("strptime failed: should throw for empty format");
22584      }
22585
22586      // Test 10: Literal percent
22587      numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d");
22588      if (ts10.year() != 2024) {
22589        throw std::runtime_error("strptime failed: literal percent parsing");
22590      }
22591
22592      std::cout << " -> tests passed" << std::endl;
22593    }
22594
22595    // ============================================================================
22596    // COMPONENT PROPERTIES TESTS
22597    // ============================================================================
22598
22599    void np_test_timestamp_properties() {
22600      std::cout << "========= timestamp: component properties ========================";
is_month_start (np_test_5_all.cpp:22585)
22575      // Test 9: Empty format should throw
22576      threw = false;
22577      try {
22578        numpy::Timestamp::strptime("2024-03-15", "");
22579      } catch (const std::invalid_argument&) {
22580        threw = true;
22581      }
22582      if (!threw) {
22583        throw std::runtime_error("strptime failed: should throw for empty format");
22584      }
22585
22586      // Test 10: Literal percent
22587      numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d");
22588      if (ts10.year() != 2024) {
22589        throw std::runtime_error("strptime failed: literal percent parsing");
22590      }
22591
22592      std::cout << " -> tests passed" << std::endl;
22593    }
22594
22595    // ============================================================================
is_quarter_end (np_test_5_all.cpp:22591)
22581      }
22582      if (!threw) {
22583        throw std::runtime_error("strptime failed: should throw for empty format");
22584      }
22585
22586      // Test 10: Literal percent
22587      numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d");
22588      if (ts10.year() != 2024) {
22589        throw std::runtime_error("strptime failed: literal percent parsing");
22590      }
22591
22592      std::cout << " -> tests passed" << std::endl;
22593    }
22594
22595    // ============================================================================
22596    // COMPONENT PROPERTIES TESTS
22597    // ============================================================================
22598
22599    void np_test_timestamp_properties() {
22600      std::cout << "========= timestamp: component properties ========================";
is_quarter_start (np_test_5_all.cpp:22586)
22576      threw = false;
22577      try {
22578        numpy::Timestamp::strptime("2024-03-15", "");
22579      } catch (const std::invalid_argument&) {
22580        threw = true;
22581      }
22582      if (!threw) {
22583        throw std::runtime_error("strptime failed: should throw for empty format");
22584      }
22585
22586      // Test 10: Literal percent
22587      numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d");
22588      if (ts10.year() != 2024) {
22589        throw std::runtime_error("strptime failed: literal percent parsing");
22590      }
22591
22592      std::cout << " -> tests passed" << std::endl;
22593    }
22594
22595    // ============================================================================
22596    // COMPONENT PROPERTIES TESTS
is_year_end (np_test_5_all.cpp:22589)
22579      } catch (const std::invalid_argument&) {
22580        threw = true;
22581      }
22582      if (!threw) {
22583        throw std::runtime_error("strptime failed: should throw for empty format");
22584      }
22585
22586      // Test 10: Literal percent
22587      numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d");
22588      if (ts10.year() != 2024) {
22589        throw std::runtime_error("strptime failed: literal percent parsing");
22590      }
22591
22592      std::cout << " -> tests passed" << std::endl;
22593    }
22594
22595    // ============================================================================
22596    // COMPONENT PROPERTIES TESTS
22597    // ============================================================================
22598
22599    void np_test_timestamp_properties() {
is_year_start (np_test_5_all.cpp:22584)
22574      // Test 9: Empty format should throw
22575      threw = false;
22576      try {
22577        numpy::Timestamp::strptime("2024-03-15", "");
22578      } catch (const std::invalid_argument&) {
22579        threw = true;
22580      }
22581      if (!threw) {
22582        throw std::runtime_error("strptime failed: should throw for empty format");
22583      }
22584
22585      // Test 10: Literal percent
22586      numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d");
22587      if (ts10.year() != 2024) {
22588        throw std::runtime_error("strptime failed: literal percent parsing");
22589      }
22590
22591      std::cout << " -> tests passed" << std::endl;
22592    }
is_zero (np_test_2_all.cpp:7329)
7319      // Test machine epsilon
7320      auto eps_double = machine_epsilon<double>();
7321      if (!(eps_double > 0)) {
7322          std::string description = std::string("test_basic_utilities():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(eps_double > 0)";
7323          std::cout << std::string("[FAIL] ") + description << std::endl;
7324          throw std::runtime_error(description);
7325      }
7326      // std::cout << "Machine epsilon (double): " << eps_double << std::endl;
7327
7328      // Test zero check
7329      bool is_zero_result = is_zero(1e-16);
7330      if (!(is_zero_result == true)) {
7331          std::string description = std::string("test_basic_utilities():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(is_zero_result == true)";
7332          std::cout << std::string("[FAIL] ") + description << std::endl;
7333          throw std::runtime_error(description);
7334      }
7335      // std::cout << "Is 1e-16 zero? " << (is_zero_result ? "Yes" : "No") << std::endl;
7336
7337      // Test safe divide
7338      double safe_result = safe_divide(1.0, 2.0);
7339      if (!(safe_result == 0.5)) {
clone (np_test_1_all.cpp:24942)
24932      }
24933
24934      // Test reproducibility
24935      numpy::random::PCG64DXSM rng2(11111);
24936      if (rng2.next_uint64() != val) {
24937        std::cout << "  [FAIL] : in np_test_bitgen_pcg64dxsm() : not reproducible";
24938        throw std::runtime_error("np_test_bitgen_pcg64dxsm failed");
24939      }
24940
24941      // Test clone
24942      auto cloned = rng.clone();
24943      if (cloned->name() != "PCG64DXSM") {
24944        std::cout << "  [FAIL] : in np_test_bitgen_pcg64dxsm() : clone name incorrect";
24945        throw std::runtime_error("np_test_bitgen_pcg64dxsm failed");
24946      }
24947
24948      std::cout << " -> tests passed" << std::endl;
24949    }
24950
24951    // ============================================================================
24952    // PHILOX TESTS
day (np_test_5_all.cpp:22185)
22175                      << std::endl;
22176            errors++;
22177        }
22178
22179        numpy::Timedelta td3("45s");
22180        if (std::abs(td3.total_seconds() - 45.0) > 0.0001) {
22181            std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec"
22182                      << std::endl;
22183            errors++;
22184        }
22185
22186        numpy::Timedelta td4("NaT");
22187        if (!td4.isNaT()) {
22188            std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT"
22189                      << std::endl;
22190            errors++;
22191        }
22192    }
22193
22194    // Stream operator
22195    {
day_name (np_test_5_all.cpp:22735)
22725      if (!pass) {
22726        std::cout << "  [FAIL] : in np_test_timestamp_timezone() : " << fail_msg;
22727        throw std::runtime_error("np_test_timestamp_timezone failed: " + fail_msg);
22728      }
22729
22730      std::cout << " -> tests passed" << std::endl;
22731    }
22732
22733    // ============================================================================
22734    // CONVERSION TESTS
22735    // ============================================================================
22736
22737    void np_test_timestamp_conversions() {
22738      std::cout << "========= timestamp: conversion methods ==========================";
22739
22740      auto pass = true;
22741      std::string fail_msg;
22742
22743      numpy::Timestamp ts(2024, 6, 15, 12, 30, 45, 123456, 789);
22744
22745      // to_datetime64
dayofweek (np_test_5_all.cpp:22547)
22537        throw std::runtime_error("strptime failed: American format parsing");
22538      }
22539
22540      // Test 4: 2-digit year
22541      numpy::Timestamp ts4 = numpy::Timestamp::strptime("03/15/24", "%m/%d/%y");
22542      if (ts4.year() != 2024) {
22543        throw std::runtime_error("strptime failed: 2-digit year parsing");
22544      }
22545
22546      // Test 5: With microseconds
22547      numpy::Timestamp ts5 = numpy::Timestamp::strptime("2024-03-15 14:30:45.123456", "%Y-%m-%d %H:%M:%S.%f");
22548      if (ts5.microsecond() != 123456) {
22549        throw std::runtime_error("strptime failed: microseconds parsing");
22550      }
22551
22552      // Test 6: 12-hour format with AM/PM
22553      numpy::Timestamp ts6 = numpy::Timestamp::strptime("03/15/2024 02:30:00 PM", "%m/%d/%Y %I:%M:%S %p");
22554      if (ts6.hour() != 14) {
22555        throw std::runtime_error("strptime failed: 12-hour format parsing");
22556      }
dayofyear (np_test_5_all.cpp:22549)
22539      // Test 4: 2-digit year
22540      numpy::Timestamp ts4 = numpy::Timestamp::strptime("03/15/24", "%m/%d/%y");
22541      if (ts4.year() != 2024) {
22542        throw std::runtime_error("strptime failed: 2-digit year parsing");
22543      }
22544
22545      // Test 5: With microseconds
22546      numpy::Timestamp ts5 = numpy::Timestamp::strptime("2024-03-15 14:30:45.123456", "%Y-%m-%d %H:%M:%S.%f");
22547      if (ts5.microsecond() != 123456) {
22548        throw std::runtime_error("strptime failed: microseconds parsing");
22549      }
22550
22551      // Test 6: 12-hour format with AM/PM
22552      numpy::Timestamp ts6 = numpy::Timestamp::strptime("03/15/2024 02:30:00 PM", "%m/%d/%Y %I:%M:%S %p");
22553      if (ts6.hour() != 14) {
22554        throw std::runtime_error("strptime failed: 12-hour format parsing");
22555      }
22556
22557      // Test 7: Day of year format
22558      numpy::Timestamp ts7 = numpy::Timestamp::strptime("2024-075", "%Y-%j");
hour (np_test_5_all.cpp:22186)
22176            errors++;
22177        }
22178
22179        numpy::Timedelta td3("45s");
22180        if (std::abs(td3.total_seconds() - 45.0) > 0.0001) {
22181            std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec"
22182                      << std::endl;
22183            errors++;
22184        }
22185
22186        numpy::Timedelta td4("NaT");
22187        if (!td4.isNaT()) {
22188            std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT"
22189                      << std::endl;
22190            errors++;
22191        }
22192    }
22193
22194    // Stream operator
22195    {
22196        numpy::Timedelta td(1, 2, 30);
microsecond (np_test_5_all.cpp:22193)
22183            errors++;
22184        }
22185
22186        numpy::Timedelta td4("NaT");
22187        if (!td4.isNaT()) {
22188            std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT"
22189                      << std::endl;
22190            errors++;
22191        }
22192    }
22193
22194    // Stream operator
22195    {
22196        numpy::Timedelta td(1, 2, 30);
22197        std::ostringstream oss;
22198        oss << td;
22199        std::string str = oss.str();
22200        if (str.empty() || str.find("days") == std::string::npos) {
22201            std::cout << "[FAIL] np_test_timedelta_edge_cases: stream operator failed"
22202                      << std::endl;
22203            errors++;
month (np_test_5_all.cpp:22185)
22175                      << std::endl;
22176            errors++;
22177        }
22178
22179        numpy::Timedelta td3("45s");
22180        if (std::abs(td3.total_seconds() - 45.0) > 0.0001) {
22181            std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec"
22182                      << std::endl;
22183            errors++;
22184        }
22185
22186        numpy::Timedelta td4("NaT");
22187        if (!td4.isNaT()) {
22188            std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT"
22189                      << std::endl;
22190            errors++;
22191        }
22192    }
22193
22194    // Stream operator
22195    {
month_name (np_test_5_all.cpp:22739)
22729      std::cout << " -> tests passed" << std::endl;
22730    }
22731
22732    // ============================================================================
22733    // CONVERSION TESTS
22734    // ============================================================================
22735
22736    void np_test_timestamp_conversions() {
22737      std::cout << "========= timestamp: conversion methods ==========================";
22738
22739      auto pass = true;
22740      std::string fail_msg;
22741
22742      numpy::Timestamp ts(2024, 6, 15, 12, 30, 45, 123456, 789);
22743
22744      // to_datetime64
22745      numpy::datetime64 dt = ts.to_datetime64();
22746      if (dt.isNaT()) { pass = false; fail_msg = "to_datetime64 should not return NaT"; }
22747
22748      // asm8 alias
names (np_test_2_all.cpp:18817)
18807      create_txt_file("test_auto_names.txt");
18808
18809      // Don't provide names - should generate f0, f1, f2, f3
18810      auto data = numpy::io::recfromtxt(csv_test_dir + "test_auto_names.txt");
18811
18812      auto dtype = data.getDType();
18813
18814      // Verify auto-generated names
18815      if (!dtype.hasField("f0") || !dtype.hasField("f1") ||
18816        !dtype.hasField("f2") || !dtype.hasField("f3")) {
18817        std::cout << "  [FAIL] : Missing auto-generated field names (f0, f1, f2, f3)";
18818        throw std::runtime_error("np_test_io_extensions_recfromtxt_auto_names failed: missing auto names");
18819      }
18820
18821      std::cout << " -> tests passed" << std::endl;
18822    }
18823
18824    // ============================================================================
18825    // ERROR HANDLING TESTS
18826    // ============================================================================
names (np_test_2_all.cpp:18817)
18807      create_txt_file("test_auto_names.txt");
18808
18809      // Don't provide names - should generate f0, f1, f2, f3
18810      auto data = numpy::io::recfromtxt(csv_test_dir + "test_auto_names.txt");
18811
18812      auto dtype = data.getDType();
18813
18814      // Verify auto-generated names
18815      if (!dtype.hasField("f0") || !dtype.hasField("f1") ||
18816        !dtype.hasField("f2") || !dtype.hasField("f3")) {
18817        std::cout << "  [FAIL] : Missing auto-generated field names (f0, f1, f2, f3)";
18818        throw std::runtime_error("np_test_io_extensions_recfromtxt_auto_names failed: missing auto names");
18819      }
18820
18821      std::cout << " -> tests passed" << std::endl;
18822    }
18823
18824    // ============================================================================
18825    // ERROR HANDLING TESTS
18826    // ============================================================================
quarter (np_test_5_all.cpp:22551)
22541      numpy::Timestamp ts4 = numpy::Timestamp::strptime("03/15/24", "%m/%d/%y");
22542      if (ts4.year() != 2024) {
22543        throw std::runtime_error("strptime failed: 2-digit year parsing");
22544      }
22545
22546      // Test 5: With microseconds
22547      numpy::Timestamp ts5 = numpy::Timestamp::strptime("2024-03-15 14:30:45.123456", "%Y-%m-%d %H:%M:%S.%f");
22548      if (ts5.microsecond() != 123456) {
22549        throw std::runtime_error("strptime failed: microseconds parsing");
22550      }
22551
22552      // Test 6: 12-hour format with AM/PM
22553      numpy::Timestamp ts6 = numpy::Timestamp::strptime("03/15/2024 02:30:00 PM", "%m/%d/%Y %I:%M:%S %p");
22554      if (ts6.hour() != 14) {
22555        throw std::runtime_error("strptime failed: 12-hour format parsing");
22556      }
22557
22558      // Test 7: Day of year format
22559      numpy::Timestamp ts7 = numpy::Timestamp::strptime("2024-075", "%Y-%j");
22560      if (ts7.month() != 3 || ts7.day() != 15) {  // Day 75 of 2024 is March 15
22561        throw std::runtime_error("strptime failed: day of year parsing");
result (np_test_1_all.cpp:6090)
6080        throw std::runtime_error(description);
6081    }
6082    // std::cout << "Timer restart test passed. Second: " << second_elapsed << " ms" << std::endl;
6083
6084    std::cout << " -> tests passed" << std::endl;
6085}
6086
6087void test_benchmark_result_storageBenchmarkSorting() {
6088    std::cout << "========= test_benchmark_result_storage =======================";
6089
6090    BenchmarkResult result("TestAlgorithm", 1000, 15.5, true, 4096);
6091
6092    if (!(result.algorithm_name == "TestAlgorithm")) {
6093        std::string description = std::string("test_benchmark_result_storageBenchmarkSorting():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(result.algorithm_name == \"TestAlgorithm\")";
6094        std::cout << std::string("[FAIL] ") + description << std::endl;
6095        throw std::runtime_error(description);
6096    }
6097    if (!(result.array_size == 1000)) {
6098        std::string description = std::string("test_benchmark_result_storageBenchmarkSorting():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(result.array_size == 1000)";
6099        std::cout << std::string("[FAIL] ") + description << std::endl;
6100        throw std::runtime_error(description);
second (np_test_5_all.cpp:22186)
22176            errors++;
22177        }
22178
22179        numpy::Timedelta td3("45s");
22180        if (std::abs(td3.total_seconds() - 45.0) > 0.0001) {
22181            std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec"
22182                      << std::endl;
22183            errors++;
22184        }
22185
22186        numpy::Timedelta td4("NaT");
22187        if (!td4.isNaT()) {
22188            std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT"
22189                      << std::endl;
22190            errors++;
22191        }
22192    }
22193
22194    // Stream operator
22195    {
22196        numpy::Timedelta td(1, 2, 30);
shift (np_test_1_all.cpp:2761)
2751        throw std::runtime_error(description);
2752    }
2753    if (!(left_array.getElementAt({3}) == 16384)) {
2754        std::string description = std::string("testBitShifts():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(left_array.getElementAt({3}) == 16384)";
2755        std::cout << std::string("[FAIL] ") + description << std::endl;
2756        throw std::runtime_error(description);
2757    }
2758
2759    // std::cout << "[OK] Left shift by array\n";
2760
2761    // Test excessive shift (should result in 0)
2762    auto excessive_left = left_shift(arr, 20); // More than 16 bits
2763    if (!(excessive_left.getElementAt({0}) == 0)) {
2764        std::string description = std::string("testBitShifts():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(excessive_left.getElementAt({0}) == 0)";
2765        std::cout << std::string("[FAIL] ") + description << std::endl;
2766        throw std::runtime_error(description);
2767    }
2768    if (!(excessive_left.getElementAt({1}) == 0)) {
2769        std::string description = std::string("testBitShifts():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(excessive_left.getElementAt({1}) == 0)";
2770        std::cout << std::string("[FAIL] ") + description << std::endl;
2771        throw std::runtime_error(description);
strftime (np_test_5_all.cpp:22727)
22717      if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; }
22718
22719      // Named timezone
22720      numpy::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York");
22721      if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; }
22722      std::string tzname = ny.tzname();
22723      if (tzname != "EDT" && tzname != "EST") { pass = false; fail_msg = "Summer should be EDT or EST"; }
22724
22725      if (!pass) {
22726        std::cout << "  [FAIL] : in np_test_timestamp_timezone() : " << fail_msg;
22727        throw std::runtime_error("np_test_timestamp_timezone failed: " + fail_msg);
22728      }
22729
22730      std::cout << " -> tests passed" << std::endl;
22731    }
22732
22733    // ============================================================================
22734    // CONVERSION TESTS
22735    // ============================================================================
22736
22737    void np_test_timestamp_conversions() {
total_seconds (np_test_5_all.cpp:21288)
21278        }
21279    }
21280
21281    // max()
21282    {
21283        numpy::Timedelta max_td = numpy::Timedelta::max();
21284        if (max_td.value() != INT64_MAX) {
21285            std::cout << "[FAIL] np_test_timedelta_static_factories: max() expected INT64_MAX"
21286                      << std::endl;
21287            errors++;
21288        }
21289    }
21290
21291    // resolution()
21292    {
21293        numpy::Timedelta res = numpy::Timedelta::resolution();
21294        if (res.value() != 1) {
21295            std::cout << "[FAIL] np_test_timedelta_static_factories: resolution() expected 1 ns"
21296                      << std::endl;
21297            errors++;
21298        }
tz (np_test_5_all.cpp:22214)
22204        }
22205    }
22206
22207    if (errors == 0) {
22208        std::cout << "np_test_timedelta_edge_cases -> tests passed" << std::endl;
22209    }
22210    return errors;
22211}
22212
22213} // namespace numpy_tests_timedelta
22214
22215// =============================================================================
22216// Main Test Runner
22217// =============================================================================
22218int np_test_timedelta_main() {
22219    int errors = 0;
22220
22221    errors += numpy_tests_timedelta::np_test_timedelta_constructors();
22222    errors += numpy_tests_timedelta::np_test_timedelta_static_factories();
22223    errors += numpy_tests_timedelta::np_test_timedelta_components();
22224    errors += numpy_tests_timedelta::np_test_timedelta_total_conversions();
tz_convert (np_test_5_all.cpp:22899)
22889      if (floored_h.hour() != 14 || floored_h.minute() != 0 || floored_h.second() != 0) {
22890        pass = false;
22891        fail_msg = "floor to hour failed";
22892      }
22893
22894      // ceil to hour
22895      numpy::Timestamp ceiled_h = ts.ceil("h");
22896      if (ceiled_h.hour() != 15 || ceiled_h.minute() != 0) {
22897        pass = false;
22898        fail_msg = "ceil to hour failed";
22899      }
22900
22901      // round to hour (37 minutes -> round up)
22902      numpy::Timestamp rounded_h = ts.round("h");
22903      if (rounded_h.hour() != 15) {
22904        pass = false;
22905        fail_msg = "round to hour should be 15 (37 > 30)";
22906      }
22907
22908      // normalize (floor to day)
22909      numpy::Timestamp normalized = ts.normalize();
tz_localize (np_test_5_all.cpp:22892)
22882      auto pass = true;
22883      std::string fail_msg;
22884
22885      numpy::Timestamp ts(2024, 6, 15, 14, 37, 45, 123456);
22886
22887      // floor to hour
22888      numpy::Timestamp floored_h = ts.floor("h");
22889      if (floored_h.hour() != 14 || floored_h.minute() != 0 || floored_h.second() != 0) {
22890        pass = false;
22891        fail_msg = "floor to hour failed";
22892      }
22893
22894      // ceil to hour
22895      numpy::Timestamp ceiled_h = ts.ceil("h");
22896      if (ceiled_h.hour() != 15 || ceiled_h.minute() != 0) {
22897        pass = false;
22898        fail_msg = "ceil to hour failed";
22899      }
22900
22901      // round to hour (37 minutes -> round up)
22902      numpy::Timestamp rounded_h = ts.round("h");
week (np_test_1_all.cpp:27347)
27337      std::cout << "========= busday_offset: forward offset =======================";
27338
27339      // Start on Monday, offset by 5 business days -> should be next Monday
27340      NDArray<datetime64> dates({ 1 });
27341      NDArray<int64_t> offsets({ 1 });
27342      dates.setElementAt({ 0 }, datetime64(19723, DateTimeUnit::Day)); // 2024-01-01 (Monday)
27343      offsets.setElementAt({ 0 }, int64_t(5));
27344
27345      auto result = busday_offset(dates, offsets);
27346
27347      // Expected: Monday + 5 business days = Monday next week (skipping weekend)
27348      datetime64 expected(19730, DateTimeUnit::Day); // 2024-01-08 (Monday)
27349
27350      if (result.getElementAt({ 0 }) != expected) {
27351        std::cout << "  [FAIL] : in test_busday_offset_forward() : incorrect offset result";
27352        throw std::runtime_error("busday_offset forward test failed");
27353      }
27354
27355      std::cout << " -> tests passed" << std::endl;
27356    }
weekday (np_test_5_all.cpp:22772)
22762      // timestamp
22763      double posix = ts.timestamp();
22764      if (posix <= 0) { pass = false; fail_msg = "POSIX timestamp should be positive"; }
22765
22766      // timetuple
22767      auto [y, mo, d, h, mi, s] = ts.timetuple();
22768      if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; }
22769
22770      // date/time tuples
22771      auto [dy, dm, dd] = ts.date();
22772      if (dy != 2024) { pass = false; fail_msg = "date tuple year"; }
22773
22774      auto [th, tmi, ts2, tus] = ts.time();
22775      if (th != 12) { pass = false; fail_msg = "time tuple hour"; }
22776
22777      // Julian date
22778      double jd = ts.to_julian_date();
22779      if (jd < 2400000) { pass = false; fail_msg = "Julian date should be reasonable"; }
22780
22781      // Ordinal
22782      int ord = ts.toordinal();
year (np_test_5_all.cpp:22185)
22175                      << std::endl;
22176            errors++;
22177        }
22178
22179        numpy::Timedelta td3("45s");
22180        if (std::abs(td3.total_seconds() - 45.0) > 0.0001) {
22181            std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec"
22182                      << std::endl;
22183            errors++;
22184        }
22185
22186        numpy::Timedelta td4("NaT");
22187        if (!td4.isNaT()) {
22188            std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT"
22189                      << std::endl;
22190            errors++;
22191        }
22192    }
22193
22194    // Stream operator
22195    {