DatetimeArray ============= .. cpp:class:: numpy::DatetimeArray numpy C++ class. Example ------- .. code-block:: cpp #include using namespace numpy; // Use DatetimeArray DatetimeArray obj; // ... operations ... Constructors ------------ .. list-table:: :widths: 55 25 20 :header-rows: 1 * - Signature - Location - Example * - ``DatetimeArray(const numpy::NDArray& data, const numpy::NDArray& mask, std::shared_ptr tz = nullptr, bool copy = false)`` - df_datetime_array.h:77 - * - ``explicit DatetimeArray(const numpy::NDArray& data, std::shared_ptr tz = nullptr)`` - df_datetime_array.h:95 - * - ``explicit DatetimeArray(const std::vector>& values, std::shared_ptr tz = nullptr)`` - df_datetime_array.h:141 - * - ``explicit DatetimeArray(const std::vector& iso_strings, std::shared_ptr tz = nullptr)`` - df_datetime_array.h:163 - Construction ------------ .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``static DatetimeArray from_sequence(const std::vector>& scalars, std::shared_ptr tz = nullptr)`` - static DatetimeArray - df_datetime_array.h:389 - Array Creation -------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``bool empty() const`` - bool - df_datetime_array.h:230 - :ref:`View ` Indexing / Selection -------------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``numpy::datetime64 at(size_t index) const`` - numpy::datetime64 - df_datetime_array.h:296 - :ref:`View ` * - ``DatetimeArray take(const std::vector& indices, bool allow_fill = false, std::optional fill_value = std::nullopt) const`` - DatetimeArray - df_datetime_array.h:343 - :ref:`View ` Statistics ---------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``std::optional max() const`` - std::optional - df_datetime_array.h:770 - :ref:`View ` * - ``std::optional min() const`` - std::optional - df_datetime_array.h:761 - :ref:`View ` * - ``IntegerArray minute() const`` - IntegerArray - df_datetime_array.h:859 - :ref:`View ` Sorting ------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``numpy::NDArray argsort(bool ascending = true, const std::string& na_position = "last") const`` - numpy::NDArray - df_datetime_array.h:690 - :ref:`View ` Linear Algebra -------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``void detect_unit()`` - void - df_datetime_array.h:1268 - * - ``DatetimeArray normalize() const`` - DatetimeArray - df_datetime_array.h:1149 - :ref:`View ` Set Operations -------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``DatetimeArray unique() const`` - DatetimeArray - df_datetime_array.h:628 - :ref:`View ` I/O --- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``numpy::NDArray to_numpy(const numpy::datetime64& na_value = numpy::datetime64::NaT()) const`` - numpy::NDArray - df_datetime_array.h:453 - :ref:`View ` * - ``std::string to_string() const`` - std::string - df_datetime_array.h:1220 - :ref:`View ` Type Handling ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``DatetimeArray copy() const`` - DatetimeArray - df_datetime_array.h:336 - :ref:`View ` Type Checking ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``BooleanArray is_leap_year() const`` - BooleanArray - df_datetime_array.h:1085 - :ref:`View ` * - ``BooleanArray is_month_end() const`` - BooleanArray - df_datetime_array.h:980 - :ref:`View ` * - ``BooleanArray is_month_start() const`` - BooleanArray - df_datetime_array.h:961 - :ref:`View ` * - ``bool is_na(size_t index) const`` - bool - df_datetime_array.h:307 - * - ``BooleanArray is_quarter_end() const`` - BooleanArray - df_datetime_array.h:1023 - :ref:`View ` * - ``BooleanArray is_quarter_start() const`` - BooleanArray - df_datetime_array.h:1002 - :ref:`View ` * - ``bool is_tz_aware() const`` - bool - df_datetime_array.h:258 - * - ``BooleanArray is_year_end() const`` - BooleanArray - df_datetime_array.h:1066 - :ref:`View ` * - ``BooleanArray is_year_start() const`` - BooleanArray - df_datetime_array.h:1047 - :ref:`View ` Other Methods ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``std::optional argmax() const`` - std::optional - df_datetime_array.h:741 - :ref:`View ` * - ``std::optional argmin() const`` - std::optional - df_datetime_array.h:721 - :ref:`View ` * - ``static DatetimeArray concat(const std::vector& arrays)`` - static DatetimeArray - df_datetime_array.h:397 - * - ``size_t count() const`` - size_t - df_datetime_array.h:466 - :ref:`View ` * - ``const numpy::NDArray& data() const`` - const numpy::NDArray& - df_datetime_array.h:269 - :ref:`View ` * - ``IntegerArray day() const`` - IntegerArray - df_datetime_array.h:821 - :ref:`View ` * - ``IntegerArray dayofweek() const`` - IntegerArray - df_datetime_array.h:897 - :ref:`View ` * - ``IntegerArray dayofyear() const`` - IntegerArray - df_datetime_array.h:918 - :ref:`View ` * - ``DatetimeArray dropna() const`` - DatetimeArray - df_datetime_array.h:440 - * - ``numpy::datetime64 dt(iso_strings[i])`` - numpy::datetime64 - df_datetime_array.h:176 - :ref:`View ` * - ``dtype_type dtype() const`` - dtype_type - df_datetime_array.h:195 - :ref:`View ` * - ``std::pair, DatetimeArray> factorize() const`` - std::pair, DatetimeArray> - df_datetime_array.h:654 - * - ``DatetimeArray fillna(const numpy::datetime64& value) const`` - DatetimeArray - df_datetime_array.h:426 - * - ``bool has_na() const`` - bool - df_datetime_array.h:479 - * - ``IntegerArray hour() const`` - IntegerArray - df_datetime_array.h:840 - :ref:`View ` * - ``numpy::NDArray isna() const`` - numpy::NDArray - df_datetime_array.h:318 - * - ``size_t len() const`` - size_t - df_datetime_array.h:237 - * - ``const numpy::NDArray& mask() const`` - const numpy::NDArray& - df_datetime_array.h:276 - :ref:`View ` * - ``IntegerArray month() const`` - IntegerArray - df_datetime_array.h:802 - :ref:`View ` * - ``size_t nbytes() const`` - size_t - df_datetime_array.h:209 - :ref:`View ` * - ``constexpr int ndim() const`` - constexpr int - df_datetime_array.h:216 - :ref:`View ` * - ``numpy::NDArray notna() const`` - numpy::NDArray - df_datetime_array.h:325 - * - ``IntegerArray quarter() const`` - IntegerArray - df_datetime_array.h:937 - :ref:`View ` * - ``std::string repr() const`` - std::string - df_datetime_array.h:1237 - * - ``IntegerArray second() const`` - IntegerArray - df_datetime_array.h:878 - :ref:`View ` * - ``std::vector shape() const`` - std::vector - df_datetime_array.h:223 - :ref:`View ` * - ``size_t size() const`` - size_t - df_datetime_array.h:202 - :ref:`View ` * - ``std::shared_ptr tz() const`` - std::shared_ptr - df_datetime_array.h:251 - :ref:`View ` * - ``DatetimeArray tz_convert(std::shared_ptr tz) const`` - DatetimeArray - df_datetime_array.h:1197 - :ref:`View ` * - ``DatetimeArray tz_convert(const std::string& tz_name) const`` - DatetimeArray - df_datetime_array.h:1211 - :ref:`View ` * - ``DatetimeArray tz_localize(std::shared_ptr tz) const`` - DatetimeArray - df_datetime_array.h:1175 - :ref:`View ` * - ``DatetimeArray tz_localize(const std::string& tz_name) const`` - DatetimeArray - df_datetime_array.h:1188 - :ref:`View ` * - ``numpy::DateTimeUnit unit() const`` - numpy::DateTimeUnit - df_datetime_array.h:244 - * - ``void validate_arrays()`` - void - df_datetime_array.h:1250 - * - ``IntegerArray year() const`` - IntegerArray - df_datetime_array.h:783 - :ref:`View ` Code Examples ------------- The following examples are extracted from the test suite. .. _example-datetimearray-empty-0: .. dropdown:: empty (np_test_1_all.cpp:6316) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6306 :emphasize-lines: 11 } void test_data_generator_emptyBenchmarkSorting() { std::cout << "========= test_data_generator_empty ======================="; DataGenerator gen(42); // Test empty data generation std::vector data = gen.generate(0, DataPattern::RANDOM); if (!(data.empty())) { std::string description = std::string("test_data_generator_emptyBenchmarkSorting():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(data.empty())"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } // std::cout << "Empty data generation test passed" << std::endl; std::cout << " -> tests passed" << std::endl; } .. _example-datetimearray-at-1: .. dropdown:: at (np_test_1_all.cpp:144) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 134 :emphasize-lines: 11 array.setElementAt({0, 0}, 1); array.setElementAt({0, 1}, 2); array.setElementAt({0, 2}, 3); array.setElementAt({1, 1}, 5); array.setElementAt({2, 2}, 9); // std::cout << "Array after setting elements:" << std::endl; //array.printArray(); // std::cout << "Element at (1,1): " << array.getElementAt({1, 1}) << std::endl; // std::cout << "Element at (2,2): " << array.getElementAt({2, 2}); std::cout << " -> tests passed" << std::endl; } void testArithmetic() { std::cout << "========= testArithmeticOperations ======================="; auto array1 = createFloat32Array({2, 2}, 5.0f); auto array2 = createFloat32Array({2, 2}, 3.0f); .. _example-datetimearray-take-2: .. dropdown:: take (np_test_5_all.cpp:4313) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 4303 :emphasize-lines: 11 for (size_t i = 0; i < 6; ++i) { arr.setElementAt({ i }, static_cast(i * 10)); // [0, 10, 20, 30, 40, 50] } // Take specific indices numpy::NDArray indices({ 3 }); indices.setElementAt({ 0 }, 5); // 50 indices.setElementAt({ 1 }, 2); // 20 indices.setElementAt({ 2 }, 0); // 0 auto result = numpy::take(arr, indices); if (result.getSize() != 3) { std::cout << " [FAIL] : in np_test_take_basic() : Wrong result size"; throw std::runtime_error("Test failed"); } if (result.getElementAt({ 0 }) != 50 || result.getElementAt({ 1 }) != 20 || result.getElementAt({ 2 }) != 0) { std::cout << " [FAIL] : in np_test_take_basic() : Wrong values extracted"; throw std::runtime_error("Test failed"); } .. _example-datetimearray-max-3: .. dropdown:: max (np_test_1_all.cpp:7274) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 7264 :emphasize-lines: 11 if (sizeof(uintp) == sizeof(void*)) { // std::cout << " -> uintp size matches pointer size"; } else { // std::cout << " ✗ uintp size doesn't match pointer size" << std::endl; } // Test range limits // std::cout << "Range Information:" << std::endl; // std::cout << " intp min: " << std::numeric_limits::min() << std::endl; // std::cout << " intp max: " << std::numeric_limits::max() << std::endl; // std::cout << " uintp max: " << std::numeric_limits::max() << std::endl; // std::cout << " longdouble digits: " << std::numeric_limits::digits << std::endl; std::cout << " -> tests passed" << std::endl; } void testComplexArithmeticExtendedTypes() { std::cout << "========= testComplexArithmeticExtendedTypes ======================="; clongdouble c1(3.0L, 4.0L); // 3 + 4i .. _example-datetimearray-min-4: .. dropdown:: min (np_test_1_all.cpp:2350) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 2340 :emphasize-lines: 11 if (i % 3 == 0) { large_array.setElementAt({i}, object_(static_cast(i))); } else if (i % 3 == 1) { large_array.setElementAt({i}, object_(static_cast(i) * 0.5)); } else { large_array.setElementAt({i}, object_(std::string("str") + std::to_string(i))); } } // Verify pattern for (size_t i = 0; i < std::min(large_size, size_t(100)); ++i) { // Check first 100 object_ obj = large_array.getElementAt({i}); if (i % 3 == 0) { if (!(obj.is_type())) { std::string description = std::string("testArrayEdgeCases():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(obj.is_type())"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } } else if (i % 3 == 1) { if (!(obj.is_type())) { std::string description = std::string("unknown_function():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(obj.is_type())"; .. _example-datetimearray-minute-5: .. dropdown:: minute (np_test_5_all.cpp:22186) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22176 :emphasize-lines: 11 errors++; } numpy::Timedelta td3("45s"); if (std::abs(td3.total_seconds() - 45.0) > 0.0001) { std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec" << std::endl; errors++; } numpy::Timedelta td4("NaT"); if (!td4.isNaT()) { std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT" << std::endl; errors++; } } // Stream operator { numpy::Timedelta td(1, 2, 30); .. _example-datetimearray-argsort-6: .. dropdown:: argsort (np_test_1_all.cpp:16841) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 16831 :emphasize-lines: 11 std::cout << "========= test_argsort ======================="; // Test 1D array argsort NDArray arr1d({ 5 }); arr1d.setElementAt({ 0 }, 30); // index 0 arr1d.setElementAt({ 1 }, 10); // index 1 arr1d.setElementAt({ 2 }, 40); // index 2 arr1d.setElementAt({ 3 }, 20); // index 3 arr1d.setElementAt({ 4 }, 50); // index 4 auto indices = argsort(arr1d); // Expected order: 10(idx1), 20(idx3), 30(idx0), 40(idx2), 50(idx4) if (!(indices.getElementAt({ 0 }) == 1)) { std::string description = std::string("test_argsort():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(indices.getElementAt({ 0 }) == 1)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } if (!(indices.getElementAt({ 1 }) == 3)) { std::string description = std::string("test_argsort():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(indices.getElementAt({ 1 }) == 3)"; std::cout << std::string("[FAIL] ") + description << std::endl; .. _example-datetimearray-normalize-7: .. dropdown:: normalize (np_test_5_all.cpp:22817) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22807 :emphasize-lines: 11 if (str.find("2024") == std::string::npos) { pass = false; fail_msg = "toString should contain year"; } // isoformat std::string iso = ts.isoformat(); if (iso.find("2024-06-15") == std::string::npos) { pass = false; fail_msg = "isoformat should contain date"; } // isoformat with space separator std::string iso_space = ts.isoformat(' '); if (iso_space.find(" ") == std::string::npos) { pass = false; fail_msg = "isoformat with space separator"; } // strftime std::string fmt = ts.strftime("%Y/%m/%d"); if (fmt != "2024/06/15") { pass = false; fail_msg = "strftime format"; } // ctime std::string ct = ts.ctime(); if (ct.find("2024") == std::string::npos) { pass = false; fail_msg = "ctime should contain year"; } // day_name std::string dayname = ts.day_name(); if (dayname != "Saturday") { pass = false; fail_msg = "2024-06-15 is Saturday"; } .. _example-datetimearray-unique-8: .. dropdown:: unique (np_test_1_all.cpp:6259) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6249 :emphasize-lines: 11 if (!(data.size() == 100)) { std::string description = std::string("test_data_generator_few_uniqueBenchmarkSorting():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(data.size() == 100)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } // Count unique values std::vector sorted_copy = data; std::sort(sorted_copy.begin(), sorted_copy.end()); auto unique_end = std::unique(sorted_copy.begin(), sorted_copy.end()); size_t unique_count = std::distance(sorted_copy.begin(), unique_end); // Should have significantly fewer unique values than total elements if (!(unique_count < data.size() / 2)) { std::string description = std::string("test_data_generator_few_uniqueBenchmarkSorting():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(unique_count < data.size() / 2)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } // std::cout << "Few unique data generation test passed. Unique values: " << unique_count << std::endl; .. _example-datetimearray-to_numpy-9: .. dropdown:: to_numpy (np_test_5_all.cpp:21373) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 21363 :emphasize-lines: 11 if (errors == 0) { std::cout << "np_test_timedelta_components -> tests passed" << std::endl; } return errors; } // ============================================================================= // Test 4: Total Conversion Properties // ============================================================================= int np_test_timedelta_total_conversions() { int errors = 0; numpy::Timedelta td(1, 12, 0); // 1 day 12 hours = 1.5 days = 36 hours // total_seconds { double secs = td.total_seconds(); double expected = (24 + 12) * 3600.0; if (std::abs(secs - expected) > 0.0001) { std::cout << "[FAIL] np_test_timedelta_total_conversions: total_seconds expected " << expected << ", got " << secs << std::endl; .. _example-datetimearray-to_string-10: .. dropdown:: to_string (np_test_1_all.cpp:454) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 444 :emphasize-lines: 11 // Modify through different views view1.setElementAt({0, 0}, 100); view2.setElementAt({2, 1}, 200); // This is (1, 2) in original view3.setElementAt({0, 0}, 300); // This is (1, 1) in original // std::cout << "After modifications through multiple views:" << std::endl; //original.printArray(); // Verify all changes are reflected if (!(original.getElementAt({0, 0}) == 100)) { std::string description = std::string("testAdvancedViewLifecycle():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(original.getElementAt({0, 0}) == 100)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } if (!(original.getElementAt({1, 2}) == 200)) { std::string description = std::string("testAdvancedViewLifecycle():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(original.getElementAt({1, 2}) == 200)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } if (!(original.getElementAt({1, 1}) == 300)) { std::string description = std::string("testAdvancedViewLifecycle():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(original.getElementAt({1, 1}) == 300)"; .. _example-datetimearray-copy-11: .. dropdown:: copy (np_test_1_all.cpp:9812) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 9802 :emphasize-lines: 11 //original.printArray(); // The modification should be at position (1,1) in original if (!(original.getElementAt({1, 1}) == 9999)) { std::string description = std::string("testSliceCopyVsViewMemoryOwnership():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(original.getElementAt({1, 1}) == 9999)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } // std::cout << "[OK] Slice view shares memory with original"; // Test slice copy (should be independent) auto slice_copy = original.sliceArray({{2, 4}, {2, 4}}); // std::cout << "Slice copy [2:4, 2:4]:"; //slice_copy.printArray(); slice_copy.setElementAt({0, 0}, 7777); // std::cout << "After modifying slice copy at (0,0):" << std::endl; // std::cout << "Original array:" << std::endl; //original.printArray(); // std::cout << "Slice copy:" << std::endl; .. _example-datetimearray-is_leap_year-12: .. dropdown:: is_leap_year (np_test_5_all.cpp:22577) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22567 :emphasize-lines: 11 numpy::Timestamp::strptime("", "%Y-%m-%d"); } catch (const std::invalid_argument&) { threw = true; } if (!threw) { throw std::runtime_error("strptime failed: should throw for empty string"); } // Test 9: Empty format should throw threw = false; try { numpy::Timestamp::strptime("2024-03-15", ""); } catch (const std::invalid_argument&) { threw = true; } if (!threw) { throw std::runtime_error("strptime failed: should throw for empty format"); } // Test 10: Literal percent numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d"); .. _example-datetimearray-is_month_end-13: .. dropdown:: is_month_end (np_test_5_all.cpp:22590) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22580 :emphasize-lines: 11 threw = true; } if (!threw) { throw std::runtime_error("strptime failed: should throw for empty format"); } // Test 10: Literal percent numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d"); if (ts10.year() != 2024) { throw std::runtime_error("strptime failed: literal percent parsing"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // COMPONENT PROPERTIES TESTS // ============================================================================ void np_test_timestamp_properties() { std::cout << "========= timestamp: component properties ========================"; .. _example-datetimearray-is_month_start-14: .. dropdown:: is_month_start (np_test_5_all.cpp:22585) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22575 :emphasize-lines: 11 // Test 9: Empty format should throw threw = false; try { numpy::Timestamp::strptime("2024-03-15", ""); } catch (const std::invalid_argument&) { threw = true; } if (!threw) { throw std::runtime_error("strptime failed: should throw for empty format"); } // Test 10: Literal percent numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d"); if (ts10.year() != 2024) { throw std::runtime_error("strptime failed: literal percent parsing"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ .. _example-datetimearray-is_quarter_end-15: .. dropdown:: is_quarter_end (np_test_5_all.cpp:22591) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22581 :emphasize-lines: 11 } if (!threw) { throw std::runtime_error("strptime failed: should throw for empty format"); } // Test 10: Literal percent numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d"); if (ts10.year() != 2024) { throw std::runtime_error("strptime failed: literal percent parsing"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // COMPONENT PROPERTIES TESTS // ============================================================================ void np_test_timestamp_properties() { std::cout << "========= timestamp: component properties ========================"; .. _example-datetimearray-is_quarter_start-16: .. dropdown:: is_quarter_start (np_test_5_all.cpp:22586) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22576 :emphasize-lines: 11 threw = false; try { numpy::Timestamp::strptime("2024-03-15", ""); } catch (const std::invalid_argument&) { threw = true; } if (!threw) { throw std::runtime_error("strptime failed: should throw for empty format"); } // Test 10: Literal percent numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d"); if (ts10.year() != 2024) { throw std::runtime_error("strptime failed: literal percent parsing"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // COMPONENT PROPERTIES TESTS .. _example-datetimearray-is_year_end-17: .. dropdown:: is_year_end (np_test_5_all.cpp:22589) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22579 :emphasize-lines: 11 } catch (const std::invalid_argument&) { threw = true; } if (!threw) { throw std::runtime_error("strptime failed: should throw for empty format"); } // Test 10: Literal percent numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d"); if (ts10.year() != 2024) { throw std::runtime_error("strptime failed: literal percent parsing"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // COMPONENT PROPERTIES TESTS // ============================================================================ void np_test_timestamp_properties() { .. _example-datetimearray-is_year_start-18: .. dropdown:: is_year_start (np_test_5_all.cpp:22584) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22574 :emphasize-lines: 11 // Test 9: Empty format should throw threw = false; try { numpy::Timestamp::strptime("2024-03-15", ""); } catch (const std::invalid_argument&) { threw = true; } if (!threw) { throw std::runtime_error("strptime failed: should throw for empty format"); } // Test 10: Literal percent numpy::Timestamp ts10 = numpy::Timestamp::strptime("100%2024-03-15", "100%%%Y-%m-%d"); if (ts10.year() != 2024) { throw std::runtime_error("strptime failed: literal percent parsing"); } std::cout << " -> tests passed" << std::endl; } .. _example-datetimearray-argmax-19: .. dropdown:: argmax (np_test_3_all.cpp:20521) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 20511 :emphasize-lines: 11 auto result = numpy::argmin(arr); // Should return 1 (index of (1,5)) if (result.getElementAt({0}) != 1) { throw std::runtime_error("argmin() failed: expected index 1"); } std::cout << "PASSED\n"; } void test_argmax_complex128() { std::cout << " Testing argmax() with complex128... "; numpy::NDArray arr({3}); arr.setElementAt({0}, complex128(3.0, 1.0)); // index 0 - largest arr.setElementAt({1}, complex128(1.0, 5.0)); // index 1 arr.setElementAt({2}, complex128(2.0, 2.0)); // index 2 auto result = numpy::argmax(arr); // Should return 0 (index of (3,1)) if (result.getElementAt({0}) != 0) { throw std::runtime_error("argmax() failed: expected index 0"); } .. _example-datetimearray-argmin-20: .. dropdown:: argmin (np_test_3_all.cpp:20506) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 20496 :emphasize-lines: 11 if (min_result.getElementAt({0}).real() != 2.0 || min_result.getElementAt({0}).imag() != 1.0) { throw std::runtime_error("min() tie-breaking failed: expected (2,1)"); } if (max_result.getElementAt({0}).real() != 2.0 || max_result.getElementAt({0}).imag() != 5.0) { throw std::runtime_error("max() tie-breaking failed: expected (2,5)"); } std::cout << "PASSED\n"; } void test_argmin_complex128() { std::cout << " Testing argmin() with complex128... "; numpy::NDArray arr({3}); arr.setElementAt({0}, complex128(3.0, 1.0)); // index 0 arr.setElementAt({1}, complex128(1.0, 5.0)); // index 1 - smallest arr.setElementAt({2}, complex128(2.0, 2.0)); // index 2 auto result = numpy::argmin(arr); // Should return 1 (index of (1,5)) if (result.getElementAt({0}) != 1) { throw std::runtime_error("argmin() failed: expected index 1"); } .. _example-datetimearray-count-21: .. dropdown:: count (np_test_1_all.cpp:3616) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3606 :emphasize-lines: 11 // Create larger arrays for performance testing auto large_arr = NDArray::createOnes({100, 100}); auto broadcast_arr = NDArray::createOnes({1, 100}); // Time the operation (basic timing) auto start = std::chrono::high_resolution_clock::now(); auto result = large_arr.addArrays(broadcast_arr); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(end - start); // std::cout << "Large array broadcasting took " << duration.count() << " microseconds" << std::endl; // Verify result shape if (!((result.getShape() == std::vector{100, 100}))) { std::string description = std::string("test_broadcasting_performance():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !((result.getShape() == std::vector{100, 100}))"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } if (!(result.getElementAt({50, 50}) == 2.0)) { std::string description = std::string("test_broadcasting_performance():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(result.getElementAt({50, 50}) == 2.0)"; std::cout << std::string("[FAIL] ") + description << std::endl; .. _example-datetimearray-data-22: .. dropdown:: data (np_test_1_all.cpp:2084) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 2074 :emphasize-lines: 11 } if (!(derived_ptr->extra == 2)) { std::string description = std::string("testObjectHolderEdgeCases():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(derived_ptr->extra == 2)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } // Test 6: Large object handling struct LargeObject { std::vector data; LargeObject() : data(10000, 3.14159) {} // Large object }; LargeObject large; object_ large_obj(large); // Should handle large objects if (!(!large_obj.is_null())) { std::string description = std::string("testObjectHolderEdgeCases():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(!large_obj.is_null())"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } if (!(large_obj.is_type())) { .. _example-datetimearray-day-23: .. dropdown:: day (np_test_5_all.cpp:22185) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22175 :emphasize-lines: 11 << std::endl; errors++; } numpy::Timedelta td3("45s"); if (std::abs(td3.total_seconds() - 45.0) > 0.0001) { std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec" << std::endl; errors++; } numpy::Timedelta td4("NaT"); if (!td4.isNaT()) { std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT" << std::endl; errors++; } } // Stream operator { .. _example-datetimearray-dayofweek-24: .. dropdown:: dayofweek (np_test_5_all.cpp:22547) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22537 :emphasize-lines: 11 throw std::runtime_error("strptime failed: American format parsing"); } // Test 4: 2-digit year numpy::Timestamp ts4 = numpy::Timestamp::strptime("03/15/24", "%m/%d/%y"); if (ts4.year() != 2024) { throw std::runtime_error("strptime failed: 2-digit year parsing"); } // Test 5: With microseconds numpy::Timestamp ts5 = numpy::Timestamp::strptime("2024-03-15 14:30:45.123456", "%Y-%m-%d %H:%M:%S.%f"); if (ts5.microsecond() != 123456) { throw std::runtime_error("strptime failed: microseconds parsing"); } // Test 6: 12-hour format with AM/PM numpy::Timestamp ts6 = numpy::Timestamp::strptime("03/15/2024 02:30:00 PM", "%m/%d/%Y %I:%M:%S %p"); if (ts6.hour() != 14) { throw std::runtime_error("strptime failed: 12-hour format parsing"); } .. _example-datetimearray-dayofyear-25: .. dropdown:: dayofyear (np_test_5_all.cpp:22549) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22539 :emphasize-lines: 11 // Test 4: 2-digit year numpy::Timestamp ts4 = numpy::Timestamp::strptime("03/15/24", "%m/%d/%y"); if (ts4.year() != 2024) { throw std::runtime_error("strptime failed: 2-digit year parsing"); } // Test 5: With microseconds numpy::Timestamp ts5 = numpy::Timestamp::strptime("2024-03-15 14:30:45.123456", "%Y-%m-%d %H:%M:%S.%f"); if (ts5.microsecond() != 123456) { throw std::runtime_error("strptime failed: microseconds parsing"); } // Test 6: 12-hour format with AM/PM numpy::Timestamp ts6 = numpy::Timestamp::strptime("03/15/2024 02:30:00 PM", "%m/%d/%Y %I:%M:%S %p"); if (ts6.hour() != 14) { throw std::runtime_error("strptime failed: 12-hour format parsing"); } // Test 7: Day of year format numpy::Timestamp ts7 = numpy::Timestamp::strptime("2024-075", "%Y-%j"); .. _example-datetimearray-dt-26: .. dropdown:: dt (np_test_2_all.cpp:21934) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 21924 :emphasize-lines: 11 {numpy::DateTimeUnit::Hour, "h"}, {numpy::DateTimeUnit::Minute, "m"}, {numpy::DateTimeUnit::Second, "s"}, {numpy::DateTimeUnit::Millisecond, "ms"}, {numpy::DateTimeUnit::Microsecond, "us"}, {numpy::DateTimeUnit::Nanosecond, "ns"} }; // Test all datetime64 units for (const auto& test : tests) { numpy::datetime64 dt(1, test.unit); auto [unit_str, count] = numpy::datetime_utils::datetime_data(dt); if (unit_str != test.expected_str || count != 1) { std::cout << " [FAIL] : in np_test_datetime_data_all_units() : datetime64 unit test failed for " << test.expected_str << ": got ('" << unit_str << "', " << count << ")" << std::endl; throw std::runtime_error("np_test_datetime_data_all_units failed: datetime64 unit mismatch"); } } std::cout << " -> tests passed" << std::endl; .. _example-datetimearray-dtype-27: .. dropdown:: dtype (np_test_3_all.cpp:7942) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 7932 :emphasize-lines: 11 if (info.max != expected_max) { std::cerr << "[FAIL] IInfo::max mismatch"; throw std::runtime_error("IInfo uint64 max test failed"); } // std::cout << "[OK] IInfo::max = " << info.max << std::endl; std::cout << " -> tests passed" << std::endl; } // ============================================================================ // dtype() Tests - DType descriptor creation // ============================================================================ void np_test_dtype_from_string_integers() { std::cout << "========= np_test_dtype_from_string_integers ======================="; // Test integer type strings if (dtype("int8") != DType::INT8) { std::cerr << "[FAIL] dtype(\"int8\") should return INT8"; throw std::runtime_error("dtype string test failed"); } .. _example-datetimearray-hour-28: .. dropdown:: hour (np_test_5_all.cpp:22186) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22176 :emphasize-lines: 11 errors++; } numpy::Timedelta td3("45s"); if (std::abs(td3.total_seconds() - 45.0) > 0.0001) { std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec" << std::endl; errors++; } numpy::Timedelta td4("NaT"); if (!td4.isNaT()) { std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT" << std::endl; errors++; } } // Stream operator { numpy::Timedelta td(1, 2, 30); .. _example-datetimearray-mask-29: .. dropdown:: mask (np_test_1_all.cpp:27691) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 27681 :emphasize-lines: 11 void test_mask_rows_cols() { std::cout << "========= ma::mask_rows() and ma::mask_cols(): mask operations ==="; auto data = numpy::array({ {1.0, 2.0, 3.0}, {4.0, 5.0, 6.0} }); auto mask = numpy::array({ {false, true, false}, {false, false, false} }); auto ma = numpy::ma::masked_array(data, mask); auto result_rows = numpy::ma::mask_rows(ma); auto result_cols = numpy::ma::mask_cols(ma); // std::cout << " ma::mask_rows(): row 0 fully masked: " << (result_rows.mask().getElementAt({ 0, 0 }) ? "true" : "false") << std::endl; // std::cout << " ma::mask_cols(): column 1 fully masked: " << (result_cols.mask().getElementAt({ 1, 1 }) ? "true" : "false"); std::cout << " -> tests passed"; } void test_compress_rowcols() { std::cout << "========= ma::compress_rowcols(): remove masked rows/columns ==="; auto data = numpy::array({ {1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0} }); auto mask = numpy::array({ {false, false, false}, {false, true, false}, {false, false, false} }); auto ma = numpy::ma::masked_array(data, mask); .. _example-datetimearray-month-30: .. dropdown:: month (np_test_5_all.cpp:22185) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22175 :emphasize-lines: 11 << std::endl; errors++; } numpy::Timedelta td3("45s"); if (std::abs(td3.total_seconds() - 45.0) > 0.0001) { std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec" << std::endl; errors++; } numpy::Timedelta td4("NaT"); if (!td4.isNaT()) { std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT" << std::endl; errors++; } } // Stream operator { .. _example-datetimearray-nbytes-31: .. dropdown:: nbytes (np_test_2_all.cpp:3547) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3537 :emphasize-lines: 11 } // Test itemsize if (!(itemsize(arr) == sizeof(double))) { std::string description = std::string("testArrayInfo():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(itemsize(arr) == sizeof(double))"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } // Test nbytes if (!(nbytes(arr) == 24 * sizeof(double))) { std::string description = std::string("testArrayInfo():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(nbytes(arr) == 24 * sizeof(double))"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } // Test flags auto flags_info = flags(arr); if (!(flags_info.owndata == true)) { std::string description = std::string("testArrayInfo():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(flags_info.owndata == true)"; std::cout << std::string("[FAIL] ") + description << std::endl; .. _example-datetimearray-ndim-32: .. dropdown:: ndim (np_test_2_all.cpp:3526) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3516 :emphasize-lines: 11 void testArrayInfo() { std::cout << "Testing array information functions...\n"; // Test basic info functions auto arr = createFloat64Array({ 2, 3, 4 }); for (size_t i = 0; i < arr.getSize(); ++i) { arr.setElementAt({ i / 12, (i / 4) % 3, i % 4 }, static_cast(i)); } // Test ndim if (!(ndim(arr) == 3)) { std::string description = std::string("testArrayInfo():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(ndim(arr) == 3)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } // Test size if (!(size(arr) == 24)) { std::string description = std::string("testArrayInfo():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(size(arr) == 24)"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); .. _example-datetimearray-quarter-33: .. dropdown:: quarter (np_test_5_all.cpp:22551) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22541 :emphasize-lines: 11 numpy::Timestamp ts4 = numpy::Timestamp::strptime("03/15/24", "%m/%d/%y"); if (ts4.year() != 2024) { throw std::runtime_error("strptime failed: 2-digit year parsing"); } // Test 5: With microseconds numpy::Timestamp ts5 = numpy::Timestamp::strptime("2024-03-15 14:30:45.123456", "%Y-%m-%d %H:%M:%S.%f"); if (ts5.microsecond() != 123456) { throw std::runtime_error("strptime failed: microseconds parsing"); } // Test 6: 12-hour format with AM/PM numpy::Timestamp ts6 = numpy::Timestamp::strptime("03/15/2024 02:30:00 PM", "%m/%d/%Y %I:%M:%S %p"); if (ts6.hour() != 14) { throw std::runtime_error("strptime failed: 12-hour format parsing"); } // Test 7: Day of year format numpy::Timestamp ts7 = numpy::Timestamp::strptime("2024-075", "%Y-%j"); if (ts7.month() != 3 || ts7.day() != 15) { // Day 75 of 2024 is March 15 throw std::runtime_error("strptime failed: day of year parsing"); .. _example-datetimearray-second-34: .. dropdown:: second (np_test_5_all.cpp:22186) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22176 :emphasize-lines: 11 errors++; } numpy::Timedelta td3("45s"); if (std::abs(td3.total_seconds() - 45.0) > 0.0001) { std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec" << std::endl; errors++; } numpy::Timedelta td4("NaT"); if (!td4.isNaT()) { std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT" << std::endl; errors++; } } // Stream operator { numpy::Timedelta td(1, 2, 30); .. _example-datetimearray-shape-35: .. dropdown:: shape (np_test_1_all.cpp:3751) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 3741 :emphasize-lines: 11 } for (size_t j = 0; j < 3; ++j) { arr3.setElementAt({0, j}, static_cast((j + 1) * 100)); // [100, 200, 300] } // Broadcast all arrays together std::vector> arrays = {arr1, arr2, arr3}; auto broadcasted = broadcast_arrays(arrays); // All should have shape (2, 3) for (const auto& arr : broadcasted) { if (!((arr.getShape() == std::vector{2, 3}))) { std::string description = std::string("test_broadcast_arrays():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !((arr.getShape() == std::vector{2, 3}))"; std::cout << std::string("[FAIL] ") + description << std::endl; throw std::runtime_error(description); } } // Check values if (!(broadcasted[0].getElementAt({0, 1}) == 2.0)) { .. _example-datetimearray-size-36: .. dropdown:: size (np_test_1_all.cpp:47) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 37 :emphasize-lines: 11 using namespace numpy; using namespace numpy::benchmark; using namespace numpy::char_; // Helper functions for array comparison tests namespace { const double TOLERANCE = 1e-10; bool allTrue(const NDArray& arr) { std::vector indices(arr.getShape().size(), 0); do { if (!arr.getElementAt(indices)) { return false; } } while (incrementIndices(indices, arr.getShape())); return true; } bool allFalse(const NDArray& arr) { std::vector indices(arr.getShape().size(), 0); .. _example-datetimearray-tz-37: .. dropdown:: tz (np_test_5_all.cpp:22214) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22204 :emphasize-lines: 11 } } if (errors == 0) { std::cout << "np_test_timedelta_edge_cases -> tests passed" << std::endl; } return errors; } } // namespace numpy_tests_timedelta // ============================================================================= // Main Test Runner // ============================================================================= int np_test_timedelta_main() { int errors = 0; errors += numpy_tests_timedelta::np_test_timedelta_constructors(); errors += numpy_tests_timedelta::np_test_timedelta_static_factories(); errors += numpy_tests_timedelta::np_test_timedelta_components(); errors += numpy_tests_timedelta::np_test_timedelta_total_conversions(); .. _example-datetimearray-tz_convert-38: .. dropdown:: tz_convert (np_test_5_all.cpp:22899) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22889 :emphasize-lines: 11 if (floored_h.hour() != 14 || floored_h.minute() != 0 || floored_h.second() != 0) { pass = false; fail_msg = "floor to hour failed"; } // ceil to hour numpy::Timestamp ceiled_h = ts.ceil("h"); if (ceiled_h.hour() != 15 || ceiled_h.minute() != 0) { pass = false; fail_msg = "ceil to hour failed"; } // round to hour (37 minutes -> round up) numpy::Timestamp rounded_h = ts.round("h"); if (rounded_h.hour() != 15) { pass = false; fail_msg = "round to hour should be 15 (37 > 30)"; } // normalize (floor to day) numpy::Timestamp normalized = ts.normalize(); .. _example-datetimearray-tz_convert-39: .. dropdown:: tz_convert (np_test_5_all.cpp:22899) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22889 :emphasize-lines: 11 if (floored_h.hour() != 14 || floored_h.minute() != 0 || floored_h.second() != 0) { pass = false; fail_msg = "floor to hour failed"; } // ceil to hour numpy::Timestamp ceiled_h = ts.ceil("h"); if (ceiled_h.hour() != 15 || ceiled_h.minute() != 0) { pass = false; fail_msg = "ceil to hour failed"; } // round to hour (37 minutes -> round up) numpy::Timestamp rounded_h = ts.round("h"); if (rounded_h.hour() != 15) { pass = false; fail_msg = "round to hour should be 15 (37 > 30)"; } // normalize (floor to day) numpy::Timestamp normalized = ts.normalize(); .. _example-datetimearray-tz_localize-40: .. dropdown:: tz_localize (np_test_5_all.cpp:22892) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22882 :emphasize-lines: 11 auto pass = true; std::string fail_msg; numpy::Timestamp ts(2024, 6, 15, 14, 37, 45, 123456); // floor to hour numpy::Timestamp floored_h = ts.floor("h"); if (floored_h.hour() != 14 || floored_h.minute() != 0 || floored_h.second() != 0) { pass = false; fail_msg = "floor to hour failed"; } // ceil to hour numpy::Timestamp ceiled_h = ts.ceil("h"); if (ceiled_h.hour() != 15 || ceiled_h.minute() != 0) { pass = false; fail_msg = "ceil to hour failed"; } // round to hour (37 minutes -> round up) numpy::Timestamp rounded_h = ts.round("h"); .. _example-datetimearray-tz_localize-41: .. dropdown:: tz_localize (np_test_5_all.cpp:22892) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22882 :emphasize-lines: 11 auto pass = true; std::string fail_msg; numpy::Timestamp ts(2024, 6, 15, 14, 37, 45, 123456); // floor to hour numpy::Timestamp floored_h = ts.floor("h"); if (floored_h.hour() != 14 || floored_h.minute() != 0 || floored_h.second() != 0) { pass = false; fail_msg = "floor to hour failed"; } // ceil to hour numpy::Timestamp ceiled_h = ts.ceil("h"); if (ceiled_h.hour() != 15 || ceiled_h.minute() != 0) { pass = false; fail_msg = "ceil to hour failed"; } // round to hour (37 minutes -> round up) numpy::Timestamp rounded_h = ts.round("h"); .. _example-datetimearray-year-42: .. dropdown:: year (np_test_5_all.cpp:22185) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22175 :emphasize-lines: 11 << std::endl; errors++; } numpy::Timedelta td3("45s"); if (std::abs(td3.total_seconds() - 45.0) > 0.0001) { std::cout << "[FAIL] np_test_timedelta_edge_cases: '45s' expected 45 sec" << std::endl; errors++; } numpy::Timedelta td4("NaT"); if (!td4.isNaT()) { std::cout << "[FAIL] np_test_timedelta_edge_cases: 'NaT' should parse to NaT" << std::endl; errors++; } } // Stream operator {