Timestamp ========= .. cpp:class:: pandas::Timestamp pandas C++ class. Example ------- .. code-block:: cpp #include using namespace pandas; // Use Timestamp Timestamp obj; // ... operations ... Constructors ------------ .. list-table:: :widths: 55 25 20 :header-rows: 1 * - Signature - Location - Example * - ``explicit Timestamp(int64_t value, const std::string& tz = "")`` - pd_timestamp.h:158 - :ref:`View ` * - ``explicit Timestamp(const std::string& ts_input, const std::string& tz = "")`` - pd_timestamp.h:215 - :ref:`View ` * - ``explicit Timestamp(const numpy::datetime64& dt, const std::string& tz = "")`` - pd_timestamp.h:449 - :ref:`View ` * - ``explicit Timestamp(const std::chrono::time_point& tp, const std::string& tz = "")`` - pd_timestamp.h:468 - :ref:`View ` Data Manipulation ----------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``Timestamp replace(int new_year = -1, int new_month = -1, int new_day = -1, int new_hour = -1, int new_minute = -1, int new_second = -1, int new_microsecond = -1, int new_nanosecond = -1, const std::string& new_tzinfo = "", int new_fold = -1) const`` - Timestamp - pd_timestamp.h:1427 - :ref:`View ` Statistics ---------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``static Timestamp max()`` - static Timestamp - pd_timestamp.h:801 - :ref:`View ` * - ``static Timestamp min()`` - static Timestamp - pd_timestamp.h:797 - :ref:`View ` * - ``int minute() const`` - int - pd_timestamp.h:845 - :ref:`View ` Comparison ---------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``Timestamp next_jan4_ts(next_jan4_nanos, "")`` - Timestamp - pd_timestamp.h:1286 - Combining --------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``static Timestamp combine(const std::tuple& date, const std::tuple& time)`` - static Timestamp - pd_timestamp.h:535 - :ref:`View ` Time Series ----------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``Timestamp tz_convert(const std::string& tz_str) const`` - Timestamp - pd_timestamp.h:1517 - :ref:`View ` * - ``Timestamp tz_localize(const std::string& tz_str) const`` - Timestamp - pd_timestamp.h:1487 - :ref:`View ` I/O --- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``numpy::datetime64 to_datetime64() const`` - numpy::datetime64 - pd_timestamp.h:1018 - :ref:`View ` * - ``double to_julian_date() const`` - double - pd_timestamp.h:1103 - :ref:`View ` * - ``int64_t to_numpy(const std::string& dtype = "numpy::datetime64[ns]", bool copy = false) const`` - int64_t - pd_timestamp.h:1032 - :ref:`View ` * - ``std::tm to_pydatetime() const`` - std::tm - pd_timestamp.h:1039 - :ref:`View ` Type Checking ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``bool is_leap_year() const`` - bool - pd_timestamp.h:941 - :ref:`View ` * - ``bool is_month_end() const`` - bool - pd_timestamp.h:953 - :ref:`View ` * - ``bool is_month_start() const`` - bool - pd_timestamp.h:947 - :ref:`View ` * - ``bool is_quarter_end() const`` - bool - pd_timestamp.h:965 - :ref:`View ` * - ``bool is_quarter_start() const`` - bool - pd_timestamp.h:959 - :ref:`View ` * - ``bool is_year_end() const`` - bool - pd_timestamp.h:977 - :ref:`View ` * - ``bool is_year_start() const`` - bool - pd_timestamp.h:971 - :ref:`View ` Other Methods ------------- .. list-table:: :widths: 40 20 15 25 :header-rows: 1 * - Signature - Return Type - Location - Example * - ``static Timestamp NaT()`` - static Timestamp - pd_timestamp.h:805 - :ref:`View ` * - ``Timestamp as_unit(const std::string& unit, bool round_ok = true) const`` - Timestamp - pd_timestamp.h:1458 - :ref:`View ` * - ``numpy::datetime64 asm8() const { return to_datetime64()`` - numpy::datetime64 - pd_timestamp.h:1024 - :ref:`View ` * - ``Timestamp astimezone(const std::string& tz_str) const`` - Timestamp - pd_timestamp.h:1539 - :ref:`View ` * - ``Timestamp ceil(const std::string& freq, const std::string& ambiguous = "raise", const std::string& nonexistent = "raise") const`` - Timestamp - pd_timestamp.h:1348 - :ref:`View ` * - ``static int64_t componentsToNanos(int year, int month, int day, int hour, int minute, int second, int microsecond, int nanosecond)`` - static int64_t - pd_timestamp.h:40 - :ref:`View ` * - ``void computeComponents() const`` - void - pd_timestamp.h:92 - * - ``std::string ctime() const`` - std::string - pd_timestamp.h:1212 - :ref:`View ` * - ``std::tuple date() const`` - std::tuple - pd_timestamp.h:1081 - :ref:`View ` * - ``int day() const`` - int - pd_timestamp.h:833 - :ref:`View ` * - ``std::string day_name(const std::string& locale = "") const`` - std::string - pd_timestamp.h:1217 - :ref:`View ` * - ``int day_of_week() const { return dayofweek()`` - int - pd_timestamp.h:895 - :ref:`View ` * - ``int day_of_year() const { return dayofyear()`` - int - pd_timestamp.h:912 - :ref:`View ` * - ``int dayofweek() const`` - int - pd_timestamp.h:878 - :ref:`View ` * - ``int dayofyear() const`` - int - pd_timestamp.h:898 - :ref:`View ` * - ``int days_in_month() const`` - int - pd_timestamp.h:931 - :ref:`View ` * - ``numpy::timedelta64 dst() const`` - numpy::timedelta64 - pd_timestamp.h:1553 - :ref:`View ` * - ``static int64_t float_epoch_to_nanos(double val, int64_t ns_mult)`` - static int64_t - pd_timestamp.h:505 - * - ``Timestamp floor(const std::string& freq, const std::string& ambiguous = "raise", const std::string& nonexistent = "raise") const`` - Timestamp - pd_timestamp.h:1320 - :ref:`View ` * - ``int fold() const`` - int - pd_timestamp.h:1009 - :ref:`View ` * - ``static Timestamp fromisocalendar(int iso_year, int iso_week, int iso_weekday)`` - static Timestamp - pd_timestamp.h:544 - :ref:`View ` * - ``static Timestamp fromisoformat(const std::string& date_string)`` - static Timestamp - pd_timestamp.h:574 - :ref:`View ` * - ``static Timestamp fromordinal(int64_t ordinal, const std::string& tz = "")`` - static Timestamp - pd_timestamp.h:526 - :ref:`View ` * - ``static Timestamp fromtimestamp(double ts, const std::string& tz = "")`` - static Timestamp - pd_timestamp.h:515 - :ref:`View ` * - ``int hour() const`` - int - pd_timestamp.h:839 - :ref:`View ` * - ``void invalidateCache()`` - void - pd_timestamp.h:88 - * - ``bool isNaT() const`` - bool - pd_timestamp.h:813 - :ref:`View ` * - ``std::tuple isocalendar() const`` - std::tuple - pd_timestamp.h:1241 - :ref:`View ` * - ``std::string isoformat(char sep = 'T', const std::string& timespec = "auto") const`` - std::string - pd_timestamp.h:1153 - :ref:`View ` * - ``int isoweekday() const`` - int - pd_timestamp.h:1300 - :ref:`View ` * - ``Timestamp jan4_ts(jan4_nanos, "")`` - Timestamp - pd_timestamp.h:555 - * - ``Timestamp jan4_ts(jan4_nanos, "")`` - Timestamp - pd_timestamp.h:1263 - * - ``int microsecond() const`` - int - pd_timestamp.h:857 - :ref:`View ` * - ``int month() const`` - int - pd_timestamp.h:827 - :ref:`View ` * - ``std::string month_name(const std::string& locale = "") const`` - std::string - pd_timestamp.h:1225 - :ref:`View ` * - ``int nanosecond() const`` - int - pd_timestamp.h:863 - :ref:`View ` * - ``Timestamp normalize() const`` - Timestamp - pd_timestamp.h:1405 - :ref:`View ` * - ``static Timestamp now(const std::string& tz = "")`` - static Timestamp - pd_timestamp.h:486 - :ref:`View ` * - ``static int64_t parseFrequencyToNanos(const std::string& freq)`` - static int64_t - pd_timestamp.h:136 - * - ``Timestamp prev_jan4_ts(prev_jan4_nanos, "")`` - Timestamp - pd_timestamp.h:1278 - * - ``int quarter() const`` - int - pd_timestamp.h:924 - :ref:`View ` * - ``Timestamp result(floored, "")`` - Timestamp - pd_timestamp.h:1335 - :ref:`View ` * - ``Timestamp result(floored, "")`` - Timestamp - pd_timestamp.h:1366 - :ref:`View ` * - ``Timestamp result(rounded, "")`` - Timestamp - pd_timestamp.h:1399 - :ref:`View ` * - ``Timestamp result(value_, "")`` - Timestamp - pd_timestamp.h:1476 - :ref:`View ` * - ``Timestamp result(utc_value, "")`` - Timestamp - pd_timestamp.h:1510 - :ref:`View ` * - ``Timestamp result(value_, "")`` - Timestamp - pd_timestamp.h:1526 - :ref:`View ` * - ``Timestamp result(value_, "")`` - Timestamp - pd_timestamp.h:1533 - :ref:`View ` * - ``Timestamp result(value_ + delta_nanos, "")`` - Timestamp - pd_timestamp.h:1581 - :ref:`View ` * - ``Timestamp result(value_ - delta_nanos, "")`` - Timestamp - pd_timestamp.h:1595 - :ref:`View ` * - ``Timestamp result(value_ + delta.value(), "")`` - Timestamp - pd_timestamp.h:1628 - :ref:`View ` * - ``Timestamp result(value_ - delta.value(), "")`` - Timestamp - pd_timestamp.h:1640 - :ref:`View ` * - ``Timestamp round(const std::string& freq, const std::string& ambiguous = "raise", const std::string& nonexistent = "raise") const`` - Timestamp - pd_timestamp.h:1379 - :ref:`View ` * - ``int second() const`` - int - pd_timestamp.h:851 - :ref:`View ` * - ``void setTimezone(std::shared_ptr tz)`` - void - pd_timestamp.h:997 - :ref:`View ` * - ``std::istringstream ss(input)`` - std::istringstream - pd_timestamp.h:392 - :ref:`View ` * - ``std::string strftime(const std::string& format) const`` - std::string - pd_timestamp.h:1203 - :ref:`View ` * - ``static Timestamp strptime(const std::string& date_string, const std::string& format)`` - static Timestamp - pd_timestamp.h:601 - :ref:`View ` * - ``Timestamp thu_ts(value_ + static_cast(days_to_thursday) \* NANOS_PER_DAY, "")`` - Timestamp - pd_timestamp.h:1257 - * - ``std::tuple time() const`` - std::tuple - pd_timestamp.h:1088 - :ref:`View ` * - ``double timestamp() const`` - double - pd_timestamp.h:1058 - :ref:`View ` * - ``std::tuple timetuple() const`` - std::tuple - pd_timestamp.h:1064 - :ref:`View ` * - ``std::tuple timetz() const`` - std::tuple - pd_timestamp.h:1095 - :ref:`View ` * - ``std::shared_ptr timezone() const`` - std::shared_ptr - pd_timestamp.h:995 - :ref:`View ` * - ``std::string toString() const`` - std::string - pd_timestamp.h:1130 - :ref:`View ` * - ``std::string toStringWithTime() const`` - std::string - pd_timestamp.h:1147 - * - ``static Timestamp today(const std::string& tz = "")`` - static Timestamp - pd_timestamp.h:494 - :ref:`View ` * - ``int toordinal() const`` - int - pd_timestamp.h:1112 - :ref:`View ` * - ``std::string tz() const`` - std::string - pd_timestamp.h:987 - :ref:`View ` * - ``std::string tz_display() const`` - std::string - pd_timestamp.h:991 - * - ``std::string tzinfo() const { return tz()`` - std::string - pd_timestamp.h:1002 - :ref:`View ` * - ``std::string tzname() const`` - std::string - pd_timestamp.h:1004 - :ref:`View ` * - ``Timestamp utc_ts(value_, "")`` - Timestamp - pd_timestamp.h:1074 - * - ``static Timestamp utcfromtimestamp(double ts)`` - static Timestamp - pd_timestamp.h:521 - :ref:`View ` * - ``static Timestamp utcnow()`` - static Timestamp - pd_timestamp.h:500 - :ref:`View ` * - ``numpy::timedelta64 utcoffset() const`` - numpy::timedelta64 - pd_timestamp.h:1544 - :ref:`View ` * - ``std::tuple utctimetuple() const`` - std::tuple - pd_timestamp.h:1070 - :ref:`View ` * - ``int64_t value() const`` - int64_t - pd_timestamp.h:869 - :ref:`View ` * - ``int week() const`` - int - pd_timestamp.h:915 - :ref:`View ` * - ``int weekday() const`` - int - pd_timestamp.h:1305 - :ref:`View ` * - ``int weekofyear() const { return week()`` - int - pd_timestamp.h:921 - * - ``int year() const`` - int - pd_timestamp.h:821 - :ref:`View ` Code Examples ------------- The following examples are extracted from the test suite. .. _example-timestamp-timestamp-0: .. dropdown:: Timestamp (pd_test_3_all.cpp:1501) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1491 :emphasize-lines: 11 } } } std::cout << " -> tests passed" << std::endl; } void pd_test_3_all_pandas_numpy_type_aliases() { std::cout << "========= pandas:: aliases for numpy time types ====="; // Case A: pandas::Timestamp == pandas::Timestamp (same type) { static_assert(std::is_same_v, "pandas::Timestamp must alias pandas::Timestamp"); pandas::Timestamp ts1("2021-01-01"); pandas::Timestamp ts2("2021-01-01"); // Stronger than toString()-comparison: pandas::Timestamp::operator== // compares the underlying nanosecond value directly, catching // representation drift that string formatting could mask. if (!(ts1 == ts2)) { throw std::runtime_error("alias Timestamp: ctor value mismatch"); .. _example-timestamp-timestamp-1: .. dropdown:: Timestamp (pd_test_3_all.cpp:1501) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1491 :emphasize-lines: 11 } } } std::cout << " -> tests passed" << std::endl; } void pd_test_3_all_pandas_numpy_type_aliases() { std::cout << "========= pandas:: aliases for numpy time types ====="; // Case A: pandas::Timestamp == pandas::Timestamp (same type) { static_assert(std::is_same_v, "pandas::Timestamp must alias pandas::Timestamp"); pandas::Timestamp ts1("2021-01-01"); pandas::Timestamp ts2("2021-01-01"); // Stronger than toString()-comparison: pandas::Timestamp::operator== // compares the underlying nanosecond value directly, catching // representation drift that string formatting could mask. if (!(ts1 == ts2)) { throw std::runtime_error("alias Timestamp: ctor value mismatch"); .. _example-timestamp-timestamp-2: .. dropdown:: Timestamp (pd_test_3_all.cpp:1501) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1491 :emphasize-lines: 11 } } } std::cout << " -> tests passed" << std::endl; } void pd_test_3_all_pandas_numpy_type_aliases() { std::cout << "========= pandas:: aliases for numpy time types ====="; // Case A: pandas::Timestamp == pandas::Timestamp (same type) { static_assert(std::is_same_v, "pandas::Timestamp must alias pandas::Timestamp"); pandas::Timestamp ts1("2021-01-01"); pandas::Timestamp ts2("2021-01-01"); // Stronger than toString()-comparison: pandas::Timestamp::operator== // compares the underlying nanosecond value directly, catching // representation drift that string formatting could mask. if (!(ts1 == ts2)) { throw std::runtime_error("alias Timestamp: ctor value mismatch"); .. _example-timestamp-timestamp-3: .. dropdown:: Timestamp (pd_test_3_all.cpp:1501) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1491 :emphasize-lines: 11 } } } std::cout << " -> tests passed" << std::endl; } void pd_test_3_all_pandas_numpy_type_aliases() { std::cout << "========= pandas:: aliases for numpy time types ====="; // Case A: pandas::Timestamp == pandas::Timestamp (same type) { static_assert(std::is_same_v, "pandas::Timestamp must alias pandas::Timestamp"); pandas::Timestamp ts1("2021-01-01"); pandas::Timestamp ts2("2021-01-01"); // Stronger than toString()-comparison: pandas::Timestamp::operator== // compares the underlying nanosecond value directly, catching // representation drift that string formatting could mask. if (!(ts1 == ts2)) { throw std::runtime_error("alias Timestamp: ctor value mismatch"); .. _example-timestamp-replace-4: .. dropdown:: replace (pd_test_1_all.cpp:6623) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 6613 :emphasize-lines: 11 } } // Test replace { std::map> float_data; float_data["X"] = {1.0, 2.0, 3.0}; float_data["Y"] = {2.0, 2.0, 4.0}; pandas::DataFrame df_repl(float_data); auto replaced = df_repl.replace(2.0, 99.0); // Check some value was replaced (crude check via string) std::string val_str = replaced.col("X").get_value_str(1); if (val_str.find("99") == std::string::npos) { std::cout << " [FAIL] : in pd_test_dataframe_manipulation() : replace didn't work" << std::endl; throw std::runtime_error("pd_test_dataframe_manipulation failed: replace"); } } // Test drop_duplicates { .. _example-timestamp-max-5: .. dropdown:: max (pd_test_1_all.cpp:771) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 761 :emphasize-lines: 11 pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true); // ordered // Test min std::optional min_val = arr.min(); if (!min_val.has_value() || *min_val != "low") { std::cout << " [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl; throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'"); } // Test max std::optional max_val = arr.max(); if (!max_val.has_value() || *max_val != "high") { std::cout << " [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl; throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'"); } // Test unordered throws for min/max pandas::CategoricalArray unordered = arr.as_unordered(); bool threw = false; try { unordered.min(); .. _example-timestamp-min-6: .. dropdown:: min (pd_test_1_all.cpp:764) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 754 :emphasize-lines: 11 } void pd_test_categorical_array_ordered_operations() { std::cout << "========= CategoricalArray: ordered operations (min/max) ======================= "; std::vector cats = {"low", "medium", "high"}; std::vector codes = {0, 2, 1, 0, -1}; // low, high, medium, low, NA pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true); // ordered // Test min std::optional min_val = arr.min(); if (!min_val.has_value() || *min_val != "low") { std::cout << " [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl; throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'"); } // Test max std::optional max_val = arr.max(); if (!max_val.has_value() || *max_val != "high") { std::cout << " [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl; throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'"); .. _example-timestamp-minute-7: .. dropdown:: minute (pd_test_1_all.cpp:7505) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 7495 :emphasize-lines: 11 std::cout << "========= minute property ============================="; std::vector> values = { make_dt(0), // Minute 0 make_dt(30 * NS_PER_MIN), // Minute 30 make_dt(59 * NS_PER_MIN) // Minute 59 }; pandas::DatetimeArray arr(values); pandas::DatetimeIndex idx(arr); auto minutes = idx.minute(); bool passed = (minutes.size() == 3); auto m0 = minutes[0]; auto m1 = minutes[1]; auto m2 = minutes[2]; passed = passed && m0.has_value() && *m0 == 0; passed = passed && m1.has_value() && *m1 == 30; passed = passed && m2.has_value() && *m2 == 59; if (!passed) { .. _example-timestamp-combine-8: .. dropdown:: combine (pd_test_2_all.cpp:1700) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1690 :emphasize-lines: 11 std::cout << "====================================== [OK] pd_test_between_time test suite ========================== " << std::endl; return 0; } } // namespace dataframe_tests // ------------------- pd_test_between_time.cpp (end) ----------------------------- // ------------------- pd_test_combine.cpp (start) ----------------------------- // dataframe_tests/pd_test_combine.cpp // Test for DataFrame.combine() - column-wise combine with another DataFrame #include #include #include #include "../pandas/pd_dataframe.h" // CRITICAL: No using namespace directives namespace dataframe_tests { namespace dataframe_tests_combine { .. _example-timestamp-tz_convert-9: .. dropdown:: tz_convert (pd_test_2_all.cpp:17874) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 17864 :emphasize-lines: 11 std::cout << "====================================== [OK] pd_test_transform test suite ========================== " << std::endl; return 0; } } // namespace dataframe_tests // ------------------- pd_test_transform.cpp (end) ----------------------------- // ------------------- pd_test_tz_convert.cpp (start) ----------------------------- // dataframe_tests/pd_test_tz_convert.cpp // Test for DataFrame.tz_convert() method #include #include #include #include "../pandas/pd_dataframe.h" namespace dataframe_tests { namespace dataframe_tests_tz_convert { void pd_test_tz_convert_basic() { .. _example-timestamp-tz_localize-10: .. dropdown:: tz_localize (pd_test_1_all.cpp:1431) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1421 :emphasize-lines: 11 "2023-06-15" }); // Initially should be timezone-naive if (arr.is_tz_aware()) { std::cout << " [FAIL] : array should be timezone-naive initially" << std::endl; throw std::runtime_error("pd_test_datetime_array_timezone failed: naive"); } // Localize to UTC auto localized = arr.tz_localize("UTC"); if (!localized.is_tz_aware()) { std::cout << " [FAIL] : localized array should be timezone-aware" << std::endl; throw std::runtime_error("pd_test_datetime_array_timezone failed: localize"); } // Verify timezone name in dtype auto dt = localized.dtype(); if (!dt.is_tz_aware()) { std::cout << " [FAIL] : dtype should be timezone-aware" << std::endl; throw std::runtime_error("pd_test_datetime_array_timezone failed: dtype tz"); .. _example-timestamp-to_datetime64-11: .. dropdown:: to_datetime64 (pd_test_timestamp_scalar.cpp:507) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 497 :emphasize-lines: 11 void np_test_timestamp_conversions() { std::cout << "========= timestamp: conversion methods =========================="; auto pass = true; std::string fail_msg; pandas::Timestamp ts(2024, 6, 15, 12, 30, 45, 123456, 789); // to_datetime64 numpy::datetime64 dt = ts.to_datetime64(); if (dt.isNaT()) { pass = false; fail_msg = "to_datetime64 should not return NaT"; } // asm8 alias numpy::datetime64 asm8 = ts.asm8(); if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; } // to_numpy int64_t value = ts.to_numpy(); if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; } .. _example-timestamp-to_julian_date-12: .. dropdown:: to_julian_date (pd_test_3_all.cpp:20400) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 20390 :emphasize-lines: 11 // CRITICAL: No using namespace directives namespace dataframe_tests { namespace dataframe_tests_misc { // ============================================================================ // Test DatetimeIndex.to_julian_date // ============================================================================ void pd_test_to_julian_date() { std::cout << "========= DatetimeIndex.to_julian_date() =================="; // Create DatetimeIndex with known dates std::vector> dates = { numpy::datetime64("2000-01-01"), numpy::datetime64("2000-01-02"), numpy::datetime64("2000-01-03") }; pandas::DatetimeArray arr(dates); pandas::DatetimeIndex idx(arr, "test_dates"); .. _example-timestamp-to_numpy-13: .. dropdown:: to_numpy (pd_test_1_all.cpp:16764) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 16754 :emphasize-lines: 11 // ===================================================================== // to_numpy Tests // ===================================================================== void pd_test_ndframe_to_numpy() { std::cout << "========= to_numpy =============================================" << std::endl; pandas::Series s({10, 20, 30}); auto arr = s.to_numpy(); bool passed = arr.getSize() == 3; if (!passed) { std::cout << " [FAIL] : in pd_test_ndframe_to_numpy() : size" << std::endl; throw std::runtime_error("pd_test_ndframe_to_numpy failed: size"); } passed = arr.getElementAt({0}) == 10 && arr.getElementAt({1}) == 20 && arr.getElementAt({2}) == 30; if (!passed) { std::cout << " [FAIL] : in pd_test_ndframe_to_numpy() : values" << std::endl; .. _example-timestamp-to_pydatetime-14: .. dropdown:: to_pydatetime (pd_test_timestamp_scalar.cpp:519) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 509 :emphasize-lines: 11 // asm8 alias numpy::datetime64 asm8 = ts.asm8(); if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; } // to_numpy int64_t value = ts.to_numpy(); if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; } // to_pydatetime std::tm tm = ts.to_pydatetime(); if (tm.tm_year != 124) { pass = false; fail_msg = "tm_year should be 124 (2024-1900)"; } if (tm.tm_mon != 5) { pass = false; fail_msg = "tm_mon should be 5 (June)"; } // timestamp double posix = ts.timestamp(); if (posix <= 0) { pass = false; fail_msg = "POSIX timestamp should be positive"; } // timetuple auto [y, mo, d, h, mi, s] = ts.timetuple(); if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; } .. _example-timestamp-is_leap_year-15: .. dropdown:: is_leap_year (pd_test_1_all.cpp:1280) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1270 :emphasize-lines: 11 } // is_month_end auto me = arr.is_month_end(); if (!me[1].has_value() || !me[1].value()) { std::cout << " [FAIL] : 2023-03-31 should be month end" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month end"); } // is_leap_year auto ly = arr.is_leap_year(); if (!ly[2].has_value() || !ly[2].value()) { std::cout << " [FAIL] : 2024 should be leap year" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: leap year"); } if (!ly[0].has_value() || ly[0].value()) { std::cout << " [FAIL] : 2023 should not be leap year" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: not leap year"); } std::cout << " -> tests passed" << std::endl; .. _example-timestamp-is_month_end-16: .. dropdown:: is_month_end (pd_test_1_all.cpp:1273) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1263 :emphasize-lines: 11 } // is_month_start auto ms = arr.is_month_start(); if (!ms[0].has_value() || !ms[0].value()) { std::cout << " [FAIL] : 2023-01-01 should be month start" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month start"); } // is_month_end auto me = arr.is_month_end(); if (!me[1].has_value() || !me[1].value()) { std::cout << " [FAIL] : 2023-03-31 should be month end" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month end"); } // is_leap_year auto ly = arr.is_leap_year(); if (!ly[2].has_value() || !ly[2].value()) { std::cout << " [FAIL] : 2024 should be leap year" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: leap year"); .. _example-timestamp-is_month_start-17: .. dropdown:: is_month_start (pd_test_1_all.cpp:1266) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1256 :emphasize-lines: 11 if (!ys[0].has_value() || !ys[0].value()) { std::cout << " [FAIL] : 2023-01-01 should be year start" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: year start"); } if (!ys[1].has_value() || ys[1].value()) { std::cout << " [FAIL] : 2023-03-31 should not be year start" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: not year start"); } // is_month_start auto ms = arr.is_month_start(); if (!ms[0].has_value() || !ms[0].value()) { std::cout << " [FAIL] : 2023-01-01 should be month start" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month start"); } // is_month_end auto me = arr.is_month_end(); if (!me[1].has_value() || !me[1].value()) { std::cout << " [FAIL] : 2023-03-31 should be month end" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month end"); .. _example-timestamp-is_quarter_end-18: .. dropdown:: is_quarter_end (pd_test_3_all.cpp:25056) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 25046 :emphasize-lines: 11 }; pandas::Series s(dates); pandas::DatetimeProperties> dt(s); if (dt.has_nat()) throw std::runtime_error("has_nat should be false for clean series"); auto ms = dt.is_month_start(); if (ms[0] != true || ms[1] != false) throw std::runtime_error("is_month_start failed"); auto me = dt.is_month_end(); if (me[1] != true || me[0] != false) throw std::runtime_error("is_month_end failed"); auto qs = dt.is_quarter_start(); if (qs[0] != true || qs[1] != false) throw std::runtime_error("is_quarter_start failed"); auto qe = dt.is_quarter_end(); if (qe[2] != true || qe[0] != false) throw std::runtime_error("is_quarter_end failed"); auto ys = dt.is_year_start(); if (ys[0] != true || ys[1] != false) throw std::runtime_error("is_year_start failed"); auto ye = dt.is_year_end(); if (ye[3] != true || ye[0] != false) throw std::runtime_error("is_year_end failed"); std::cout << " -> tests passed" << std::endl; } void pd_test_dt_bool_na_with_nat() { std::cout << "========= pd_test_dt_bool_na: series with NaT =========="; .. _example-timestamp-is_quarter_start-19: .. dropdown:: is_quarter_start (pd_test_3_all.cpp:25054) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 25044 :emphasize-lines: 11 numpy::datetime64("2024-03-31"), numpy::datetime64("2024-12-31") }; pandas::Series s(dates); pandas::DatetimeProperties> dt(s); if (dt.has_nat()) throw std::runtime_error("has_nat should be false for clean series"); auto ms = dt.is_month_start(); if (ms[0] != true || ms[1] != false) throw std::runtime_error("is_month_start failed"); auto me = dt.is_month_end(); if (me[1] != true || me[0] != false) throw std::runtime_error("is_month_end failed"); auto qs = dt.is_quarter_start(); if (qs[0] != true || qs[1] != false) throw std::runtime_error("is_quarter_start failed"); auto qe = dt.is_quarter_end(); if (qe[2] != true || qe[0] != false) throw std::runtime_error("is_quarter_end failed"); auto ys = dt.is_year_start(); if (ys[0] != true || ys[1] != false) throw std::runtime_error("is_year_start failed"); auto ye = dt.is_year_end(); if (ye[3] != true || ye[0] != false) throw std::runtime_error("is_year_end failed"); std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-is_year_end-20: .. dropdown:: is_year_end (pd_test_3_all.cpp:25060) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 25050 :emphasize-lines: 11 auto ms = dt.is_month_start(); if (ms[0] != true || ms[1] != false) throw std::runtime_error("is_month_start failed"); auto me = dt.is_month_end(); if (me[1] != true || me[0] != false) throw std::runtime_error("is_month_end failed"); auto qs = dt.is_quarter_start(); if (qs[0] != true || qs[1] != false) throw std::runtime_error("is_quarter_start failed"); auto qe = dt.is_quarter_end(); if (qe[2] != true || qe[0] != false) throw std::runtime_error("is_quarter_end failed"); auto ys = dt.is_year_start(); if (ys[0] != true || ys[1] != false) throw std::runtime_error("is_year_start failed"); auto ye = dt.is_year_end(); if (ye[3] != true || ye[0] != false) throw std::runtime_error("is_year_end failed"); std::cout << " -> tests passed" << std::endl; } void pd_test_dt_bool_na_with_nat() { std::cout << "========= pd_test_dt_bool_na: series with NaT =========="; std::vector dates = { numpy::datetime64("2024-01-01"), numpy::datetime64(), // NaT numpy::datetime64("2024-12-31") .. _example-timestamp-is_year_start-21: .. dropdown:: is_year_start (pd_test_1_all.cpp:1255) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1245 :emphasize-lines: 11 std::cout << "========= DatetimeArray: boolean properties ======================= "; pandas::DatetimeArray arr(std::vector{ "2023-01-01", // year start, month start "2023-03-31", // quarter end, month end "2024-02-29", // leap year (2024 is leap year) "2023-12-31" // year end, month end }); // is_year_start auto ys = arr.is_year_start(); if (!ys[0].has_value() || !ys[0].value()) { std::cout << " [FAIL] : 2023-01-01 should be year start" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: year start"); } if (!ys[1].has_value() || ys[1].value()) { std::cout << " [FAIL] : 2023-03-31 should not be year start" << std::endl; throw std::runtime_error("pd_test_datetime_array_boolean_props failed: not year start"); } // is_month_start .. _example-timestamp-nat-22: .. dropdown:: NaT (pd_test_1_all.cpp:1305) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1295 :emphasize-lines: 11 pandas::DatetimeArray arr(std::vector{ "2023-06-15", "NaT", "2023-01-01", "2023-12-31" }); // argsort ascending auto indices = arr.argsort(true, "last"); // Expected order: 2023-01-01(2), 2023-06-15(0), 2023-12-31(3), NaT(1) if (indices.getElementAt({0}) != 2) { std::cout << " [FAIL] : argsort: first should be index 2 (2023-01-01)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: argsort first"); } if (indices.getElementAt({3}) != 1) { std::cout << " [FAIL] : argsort: last should be index 1 (NaT)" << std::endl; throw std::runtime_error("pd_test_datetime_array_sorting failed: NaT position"); } // argmin .. _example-timestamp-as_unit-23: .. dropdown:: as_unit (pd_test_1_all.cpp:9361) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 9351 :emphasize-lines: 11 data.setElementAt({1}, numpy::datetime64(2000000000LL, numpy::DateTimeUnit::Nanosecond)); // 2 seconds in ns numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeTDMixin idx(arr, "test"); // Convert to microseconds pandas::DatetimeTDMixin us_idx = idx.as_unit("us"); // Convert to same unit (should return identical) pandas::DatetimeTDMixin same_idx = idx.as_unit("ns"); bool passed = (us_idx.size() == 2 && same_idx.size() == 2 && us_idx.name().has_value() && *us_idx.name() == "test"); if (!passed) { std::cout << " [FAIL] : in pd_test_datetime_as_unit() : as_unit check failed" << std::endl; throw std::runtime_error("pd_test_datetime_as_unit failed"); } .. _example-timestamp-asm8-24: .. dropdown:: asm8 (pd_test_timestamp_scalar.cpp:511) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 501 :emphasize-lines: 11 auto pass = true; std::string fail_msg; pandas::Timestamp ts(2024, 6, 15, 12, 30, 45, 123456, 789); // to_datetime64 numpy::datetime64 dt = ts.to_datetime64(); if (dt.isNaT()) { pass = false; fail_msg = "to_datetime64 should not return NaT"; } // asm8 alias numpy::datetime64 asm8 = ts.asm8(); if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; } // to_numpy int64_t value = ts.to_numpy(); if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; } // to_pydatetime std::tm tm = ts.to_pydatetime(); if (tm.tm_year != 124) { pass = false; fail_msg = "tm_year should be 124 (2024-1900)"; } if (tm.tm_mon != 5) { pass = false; fail_msg = "tm_mon should be 5 (June)"; } .. _example-timestamp-astimezone-25: .. dropdown:: astimezone (pd_test_timestamp_scalar.cpp:757) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 747 :emphasize-lines: 11 fail_msg = "tz_localize should set timezone"; } // tz_convert pandas::Timestamp converted = localized.tz_convert("Europe/London"); if (converted.tz() != "Europe/London") { pass = false; fail_msg = "tz_convert should change timezone"; } // astimezone (alias) pandas::Timestamp ast = localized.astimezone("UTC"); if (ast.tz() != "UTC") { pass = false; fail_msg = "astimezone should convert to UTC"; } // utcoffset numpy::timedelta64 offset = localized.utcoffset(); if (offset.isNaT()) { pass = false; .. _example-timestamp-ceil-26: .. dropdown:: ceil (pd_test_1_all.cpp:4949) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 4939 :emphasize-lines: 11 throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed"); } auto f = a.floor(); passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001; if (!passed) { std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl; throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed"); } auto c = a.ceil(); passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001; if (!passed) { std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl; throw std::runtime_error("pd_test_arithmetic_series_round failed: ceil failed"); } // Round with decimals pandas::Series b({1.234, 2.567, 3.891}); auto r2 = b.round(2); passed = std::abs(r2[0] - 1.23) < 0.001 && std::abs(r2[1] - 2.57) < 0.001; .. _example-timestamp-componentstonanos-27: .. dropdown:: componentsToNanos (pd_test_3_all.cpp:25149) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 25139 :emphasize-lines: 11 void pd_test_datetime_utils_nanos_epoch() { std::cout << "========= nanos_to_timestamp_str: epoch ================"; auto result = pandas::datetime_utils::nanos_to_timestamp_str(0); if (result != "1970-01-01 00:00:00") throw std::runtime_error("nanos_to_str epoch: got " + result); std::cout << " -> tests passed" << std::endl; } void pd_test_datetime_utils_nanos_simple() { std::cout << "========= nanos_to_timestamp_str: 2023-06-15 12:30:45 =="; int64_t ns = pandas::Timestamp::componentsToNanos(2023, 6, 15, 12, 30, 45, 0, 0); auto result = pandas::datetime_utils::nanos_to_timestamp_str(ns); if (result != "2023-06-15 12:30:45") throw std::runtime_error("nanos_to_str simple: got " + result); std::cout << " -> tests passed" << std::endl; } void pd_test_datetime_utils_nanos_pre_epoch() { std::cout << "========= nanos_to_timestamp_str: pre-epoch 1960 ======="; int64_t ns = pandas::Timestamp::componentsToNanos(1960, 1, 1, 0, 0, 0, 0, 0); auto result = pandas::datetime_utils::nanos_to_timestamp_str(ns); .. _example-timestamp-ctime-28: .. dropdown:: ctime (pd_test_timestamp_scalar.cpp:583) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 573 :emphasize-lines: 11 // 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"; } // month_name std::string monthname = ts.month_name(); if (monthname != "June") { pass = false; fail_msg = "Month should be June"; } .. _example-timestamp-date-29: .. dropdown:: date (pd_test_2_all.cpp:21549) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 21539 :emphasize-lines: 11 std::cout << " -- test_pivot_grouper_mixed_plain --" << std::endl; // Mix plain column and grouper auto df = make_df( {"date", "region", "product", "sales"}, {{"2023-01-15", "2023-01-20", "2023-02-10", "2023-02-25"}, {"East", "West", "East", "West"}, {"A", "B", "A", "B"}, {"100", "200", "150", "250"}}); // index: region (plain) + date (grouper with freq) std::vector> idx_groupers = { {"region", ""}, // plain column (empty freq) {"date", "ME"} // grouper with monthly freq }; std::vector> col_groupers = {}; auto result = pandas::detail::pivot_table_with_grouper( df, {"sales"}, idx_groupers, col_groupers, "sum"); check(result.nrows() > 0, "has_rows"); .. _example-timestamp-day-30: .. dropdown:: day (pd_test_1_all.cpp:1193) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1183 :emphasize-lines: 11 std::cout << " [FAIL] : month[0] should be 3" << std::endl; throw std::runtime_error("pd_test_datetime_array_component_month_day failed: month[0]"); } auto m1 = months[1]; if (!m1.has_value() || m1.value() != 12) { std::cout << " [FAIL] : month[1] should be 12" << std::endl; throw std::runtime_error("pd_test_datetime_array_component_month_day failed: month[1]"); } // Day auto days = arr.day(); auto d0 = days[0]; if (!d0.has_value() || d0.value() != 15) { std::cout << " [FAIL] : day[0] should be 15" << std::endl; throw std::runtime_error("pd_test_datetime_array_component_month_day failed: day[0]"); } auto d1 = days[1]; if (!d1.has_value() || d1.value() != 25) { std::cout << " [FAIL] : day[1] should be 25" << std::endl; throw std::runtime_error("pd_test_datetime_array_component_month_day failed: day[1]"); } .. _example-timestamp-day_name-31: .. dropdown:: day_name (pd_test_1_all.cpp:8474) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 8464 :emphasize-lines: 11 void pd_test_datetime_mixin_day_name() { std::cout << "========= day_name ===================================="; std::vector> values = { numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond) // 1970-01-01 = Thursday }; pandas::DatetimeArray arr(values); pandas::DatetimeMixinIndex idx(arr); std::vector names = idx.day_name(); bool passed = (names.size() == 1 && names[0] == "Thursday"); if (!passed) { std::cout << " [FAIL] : in pd_test_datetime_mixin_day_name() got: " << names[0] << std::endl; throw std::runtime_error("pd_test_datetime_mixin_day_name failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-day_of_week-32: .. dropdown:: day_of_week (pd_test_3_all.cpp:22018) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22008 :emphasize-lines: 11 void test_dt_aliases() { std::cout << "========= dt accessor aliases ===================="; std::vector dates = { numpy::datetime64("2023-01-15"), numpy::datetime64("2023-06-20") }; pandas::Series s(dates); auto dow1 = s.dt().dayofweek(); auto dow2 = s.dt().day_of_week(); auto dow3 = s.dt().weekday(); if (dow1[0] != dow2[0] || dow1[0] != dow3[0]) { throw std::runtime_error("dt aliases: dayofweek/day_of_week/weekday mismatch"); } auto doy1 = s.dt().dayofyear(); auto doy2 = s.dt().day_of_year(); if (doy1[0] != doy2[0]) { .. _example-timestamp-day_of_year-33: .. dropdown:: day_of_year (pd_test_3_all.cpp:22026) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22016 :emphasize-lines: 11 auto dow1 = s.dt().dayofweek(); auto dow2 = s.dt().day_of_week(); auto dow3 = s.dt().weekday(); if (dow1[0] != dow2[0] || dow1[0] != dow3[0]) { throw std::runtime_error("dt aliases: dayofweek/day_of_week/weekday mismatch"); } auto doy1 = s.dt().dayofyear(); auto doy2 = s.dt().day_of_year(); if (doy1[0] != doy2[0]) { throw std::runtime_error("dt aliases: dayofyear/day_of_year mismatch"); } std::cout << " -> tests passed" << std::endl; } void test_dt_days_in_month() { std::cout << "========= dt.days_in_month ======================"; .. _example-timestamp-dayofweek-34: .. dropdown:: dayofweek (pd_test_1_all.cpp:7565) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 7555 :emphasize-lines: 11 // 1970-01-01 was a Thursday (day 3) std::vector> values = { make_dt(0), // Thursday (3) make_dt(NS_PER_DAY), // Friday (4) make_dt(2 * NS_PER_DAY), // Saturday (5) make_dt(3 * NS_PER_DAY) // Sunday (6) }; pandas::DatetimeArray arr(values); pandas::DatetimeIndex idx(arr); auto dow = idx.dayofweek(); bool passed = (dow.size() == 4); if (!passed) { std::cout << " [FAIL] : in pd_test_datetime_index_dayofweek()" << std::endl; throw std::runtime_error("pd_test_datetime_index_dayofweek failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-dayofyear-35: .. dropdown:: dayofyear (pd_test_3_all.cpp:18582) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 18572 :emphasize-lines: 11 auto seconds = s.dt().second(); if (seconds[0] != 45 || seconds[1] != 30 || seconds[2] != 59) { std::cout << " [FAIL] : second() failed" << std::endl; throw std::runtime_error("pd_test_dt_time_components: second() failed"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // Test dt().dayofweek(), dt().dayofyear(), dt().quarter() // ============================================================================ void pd_test_dt_derived_properties() { std::cout << "========= Series.dt().dayofweek/dayofyear/quarter() ======"; // 2020-01-01 is a Wednesday (dayofweek=2), dayofyear=1, Q1 // 2020-07-04 is a Saturday (dayofweek=5), dayofyear=186, Q3 pandas::Series s({"2020-01-01", "2020-07-04"}); auto dow = s.dt().dayofweek(); .. _example-timestamp-days_in_month-36: .. dropdown:: days_in_month (pd_test_1_all.cpp:2766) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 2756 :emphasize-lines: 11 std::cout << " [FAIL] : day[0] should be 15" << std::endl; throw std::runtime_error("pd_test_period_array_day_components failed: day[0]"); } auto d1 = days[1]; if (!d1.has_value() || d1.value() != 25) { std::cout << " [FAIL] : day[1] should be 25" << std::endl; throw std::runtime_error("pd_test_period_array_day_components failed: day[1]"); } // Days in month auto dim = arr.days_in_month(); auto dim0 = dim[0]; if (!dim0.has_value() || dim0.value() != 31) { std::cout << " [FAIL] : days_in_month[0] should be 31 (March)" << std::endl; throw std::runtime_error("pd_test_period_array_day_components failed: days_in_month[0]"); } auto dim1 = dim[1]; if (!dim1.has_value() || dim1.value() != 31) { std::cout << " [FAIL] : days_in_month[1] should be 31 (December)" << std::endl; throw std::runtime_error("pd_test_period_array_day_components failed: days_in_month[1]"); } .. _example-timestamp-dst-37: .. dropdown:: dst (pd_test_timestamp_scalar.cpp:772) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 762 :emphasize-lines: 11 } // utcoffset numpy::timedelta64 offset = localized.utcoffset(); if (offset.isNaT()) { pass = false; fail_msg = "utcoffset should not be NaT"; } // dst numpy::timedelta64 dst_val = localized.dst(); if (dst_val.isNaT()) { pass = false; fail_msg = "dst should not be NaT"; } if (!pass) { std::cout << " [FAIL] : in np_test_timestamp_tz_methods() : " << fail_msg; throw std::runtime_error("np_test_timestamp_tz_methods failed: " + fail_msg); } .. _example-timestamp-floor-38: .. dropdown:: floor (pd_test_1_all.cpp:4942) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 4932 :emphasize-lines: 11 pandas::Series a({1.4, 2.5, 3.6, -1.4, -2.5}); auto r = a.round(); bool passed = std::abs(r[0] - 1.0) < 0.001 && std::abs(r[2] - 4.0) < 0.001; if (!passed) { std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : round failed" << std::endl; throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed"); } auto f = a.floor(); passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001; if (!passed) { std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl; throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed"); } auto c = a.ceil(); passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001; if (!passed) { std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl; .. _example-timestamp-fold-39: .. dropdown:: fold (pd_test_timestamp_scalar.cpp:478) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 468 :emphasize-lines: 11 std::string fail_msg; // Naive timestamp pandas::Timestamp naive(2024, 6, 15); if (!naive.tz().empty()) { pass = false; fail_msg = "Naive should have empty tz"; } if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; } // UTC timestamp pandas::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC"); if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; } if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; } // Named timezone pandas::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York"); if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; } std::string tzname = ny.tzname(); if (tzname != "EDT" && tzname != "EST") { pass = false; fail_msg = "Summer should be EDT or EST"; } if (!pass) { std::cout << " [FAIL] : in np_test_timestamp_timezone() : " << fail_msg; throw std::runtime_error("np_test_timestamp_timezone failed: " + fail_msg); .. _example-timestamp-fromisocalendar-40: .. dropdown:: fromisocalendar (pd_test_timestamp_scalar.cpp:153) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 143 :emphasize-lines: 11 } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // STATIC FACTORY METHODS - Plan 11 (fromisocalendar, fromisoformat, strptime) // ============================================================================ void np_test_timestamp_fromisocalendar() { std::cout << "========= Timestamp::fromisocalendar() ==============="; // Test 1: Basic ISO calendar to date conversion // 2024, week 1, Monday (Jan 1, 2024 was Monday of week 1) pandas::Timestamp ts1 = pandas::Timestamp::fromisocalendar(2024, 1, 1); if (ts1.year() != 2024 || ts1.month() != 1 || ts1.day() != 1) { throw std::runtime_error("fromisocalendar failed: 2024-W01-1 should be 2024-01-01"); } // Test 2: 2020, week 1, Wednesday (Jan 1, 2020 was Wednesday) pandas::Timestamp ts2 = pandas::Timestamp::fromisocalendar(2020, 1, 3); .. _example-timestamp-fromisoformat-41: .. dropdown:: fromisoformat (pd_test_timestamp_scalar.cpp:210) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 200 :emphasize-lines: 11 threw = true; } if (!threw) { throw std::runtime_error("fromisocalendar failed: should throw for weekday 8"); } std::cout << " -> tests passed" << std::endl; } void np_test_timestamp_fromisoformat() { std::cout << "========= Timestamp::fromisoformat() =================="; // Test 1: Date only pandas::Timestamp ts1 = pandas::Timestamp::fromisoformat("2024-03-15"); if (ts1.year() != 2024 || ts1.month() != 3 || ts1.day() != 15) { throw std::runtime_error("fromisoformat failed: date only parsing"); } // Test 2: Date and time with T separator pandas::Timestamp ts2 = pandas::Timestamp::fromisoformat("2024-03-15T14:30:00"); if (ts2.year() != 2024 || ts2.month() != 3 || ts2.day() != 15 || .. _example-timestamp-fromordinal-42: .. dropdown:: fromordinal (pd_test_timestamp_scalar.cpp:118) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 108 :emphasize-lines: 11 } // fromtimestamp - Unix epoch pandas::Timestamp epoch = pandas::Timestamp::fromtimestamp(0.0); if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) { pass = false; fail_msg = "fromtimestamp(0) should be epoch"; } // fromordinal pandas::Timestamp from_ord = pandas::Timestamp::fromordinal(738678); if (from_ord.isNaT()) { pass = false; fail_msg = "fromordinal should not return NaT"; } // combine pandas::Timestamp combined = pandas::Timestamp::combine({2024, 6, 15}, {12, 30, 45, 0}); if (combined.year() != 2024 || combined.hour() != 12) { pass = false; fail_msg = "combine() values incorrect"; .. _example-timestamp-fromtimestamp-43: .. dropdown:: fromtimestamp (pd_test_timestamp_scalar.cpp:111) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 101 :emphasize-lines: 11 } // utcnow() pandas::Timestamp utcnow = pandas::Timestamp::utcnow(); if (utcnow.isNaT() || utcnow.tz() != "UTC") { pass = false; fail_msg = "utcnow() should have UTC timezone"; } // fromtimestamp - Unix epoch pandas::Timestamp epoch = pandas::Timestamp::fromtimestamp(0.0); if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) { pass = false; fail_msg = "fromtimestamp(0) should be epoch"; } // fromordinal pandas::Timestamp from_ord = pandas::Timestamp::fromordinal(738678); if (from_ord.isNaT()) { pass = false; fail_msg = "fromordinal should not return NaT"; .. _example-timestamp-hour-44: .. dropdown:: hour (pd_test_1_all.cpp:7476) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 7466 :emphasize-lines: 11 std::cout << "========= hour property ==============================="; std::vector> values = { make_dt(0), // Hour 0 make_dt(6 * NS_PER_HOUR), // Hour 6 make_dt(23 * NS_PER_HOUR) // Hour 23 }; pandas::DatetimeArray arr(values); pandas::DatetimeIndex idx(arr); auto hours = idx.hour(); bool passed = (hours.size() == 3); auto h0 = hours[0]; auto h1 = hours[1]; auto h2 = hours[2]; passed = passed && h0.has_value() && *h0 == 0; passed = passed && h1.has_value() && *h1 == 6; passed = passed && h2.has_value() && *h2 == 23; if (!passed) { .. _example-timestamp-isnat-45: .. dropdown:: isNaT (pd_test_3_all.cpp:1523) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1513 :emphasize-lines: 11 } // Case B: pandas::Timedelta == pandas::Timedelta { static_assert(std::is_same_v, "pandas::Timedelta must alias pandas::Timedelta"); } // Case C: pandas::NaT is a NaT-valued Timestamp { if (!pandas::NaT.isNaT()) { throw std::runtime_error("pandas::NaT is not a NaT value"); } pandas::Timestamp default_ts; if (default_ts.isNaT() != pandas::NaT.isNaT()) { throw std::runtime_error( "pandas::NaT and default Timestamp NaT-state mismatch"); } } // Case D: round-trip - reproduces the failing test pattern .. _example-timestamp-isocalendar-46: .. dropdown:: isocalendar (pd_test_3_all.cpp:22134) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 22124 :emphasize-lines: 11 } void test_dt_isocalendar() { std::cout << "========= dt.isocalendar ========================="; std::vector dates = { numpy::datetime64("2023-01-15") }; pandas::Series s(dates); auto iso = s.dt().isocalendar(); if (iso.year.size() != 1 || iso.week.size() != 1 || iso.day.size() != 1) { throw std::runtime_error("dt.isocalendar: wrong size"); } if (iso.year[0] != 2023) { throw std::runtime_error("dt.isocalendar: wrong year"); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-isoformat-47: .. dropdown:: isoformat (pd_test_timedelta_scalar.cpp:465) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 455 :emphasize-lines: 11 if (nat.toString() != "NaT") { std::cout << "[FAIL] np_test_timedelta_strings: toString(NaT) expected 'NaT', got '" << nat.toString() << "'" << std::endl; errors++; } } // isoformat { pandas::Timedelta td(1, 2, 30); std::string iso = td.isoformat(); if (iso.find("P1D") == std::string::npos) { std::cout << "[FAIL] np_test_timedelta_strings: isoformat expected 'P1D...', got '" << iso << "'" << std::endl; errors++; } } // components_str { pandas::Timedelta td(1, 2, 30, 45, 100, 200, 300); .. _example-timestamp-isoweekday-48: .. dropdown:: isoweekday (pd_test_timestamp_scalar.cpp:620) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 610 :emphasize-lines: 11 std::string fail_msg; pandas::Timestamp ts(2024, 6, 15); // isocalendar auto [iso_year, iso_week, iso_day] = ts.isocalendar(); if (iso_year != 2024) { pass = false; fail_msg = "ISO year should be 2024"; } if (iso_week < 1 || iso_week > 53) { pass = false; fail_msg = "ISO week range"; } if (iso_day < 1 || iso_day > 7) { pass = false; fail_msg = "ISO day range 1-7"; } // isoweekday (1=Monday, 7=Sunday) int isowd = ts.isoweekday(); if (isowd != 6) { pass = false; fail_msg = "2024-06-15 is Saturday = 6"; } // weekday (0=Monday, 6=Sunday) int wd = ts.weekday(); if (wd != 5) { pass = false; fail_msg = "2024-06-15 is Saturday = 5"; } if (!pass) { std::cout << " [FAIL] : in np_test_timestamp_calendar() : " << fail_msg; throw std::runtime_error("np_test_timestamp_calendar failed: " + fail_msg); .. _example-timestamp-microsecond-49: .. dropdown:: microsecond (pd_test_timestamp_scalar.cpp:45) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 35 :emphasize-lines: 11 // Component constructor pandas::Timestamp ts1(2024, 6, 15, 14, 30, 45); if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 || ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) { pass = false; fail_msg = "Component constructor values incorrect"; } // With microseconds and nanoseconds pandas::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789); if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) { pass = false; fail_msg = "Microsecond/nanosecond values incorrect"; } // String constructor - ISO format pandas::Timestamp ts3("2024-06-15T14:30:45"); if (ts3.year() != 2024 || ts3.month() != 6 || ts3.day() != 15) { pass = false; fail_msg = "String constructor parse failed"; } .. _example-timestamp-month-50: .. dropdown:: month (pd_test_1_all.cpp:1180) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1170 :emphasize-lines: 11 void pd_test_datetime_array_component_month_day() { std::cout << "========= DatetimeArray: month/day components ======================= "; pandas::DatetimeArray arr(std::vector{ "2023-03-15", "2023-12-25", "NaT" }); // Month auto months = arr.month(); auto m0 = months[0]; if (!m0.has_value() || m0.value() != 3) { std::cout << " [FAIL] : month[0] should be 3" << std::endl; throw std::runtime_error("pd_test_datetime_array_component_month_day failed: month[0]"); } auto m1 = months[1]; if (!m1.has_value() || m1.value() != 12) { std::cout << " [FAIL] : month[1] should be 12" << std::endl; throw std::runtime_error("pd_test_datetime_array_component_month_day failed: month[1]"); } .. _example-timestamp-month_name-51: .. dropdown:: month_name (pd_test_1_all.cpp:8454) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 8444 :emphasize-lines: 11 void pd_test_datetime_mixin_month_name() { std::cout << "========= month_name =================================="; std::vector> values = { numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond) // 1970-01-01 = January }; pandas::DatetimeArray arr(values); pandas::DatetimeMixinIndex idx(arr); std::vector names = idx.month_name(); bool passed = (names.size() == 1 && names[0] == "January"); if (!passed) { std::cout << " [FAIL] : in pd_test_datetime_mixin_month_name() got: " << names[0] << std::endl; throw std::runtime_error("pd_test_datetime_mixin_month_name failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-nanosecond-52: .. dropdown:: nanosecond (pd_test_timestamp_scalar.cpp:45) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 35 :emphasize-lines: 11 // Component constructor pandas::Timestamp ts1(2024, 6, 15, 14, 30, 45); if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 || ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) { pass = false; fail_msg = "Component constructor values incorrect"; } // With microseconds and nanoseconds pandas::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789); if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) { pass = false; fail_msg = "Microsecond/nanosecond values incorrect"; } // String constructor - ISO format pandas::Timestamp ts3("2024-06-15T14:30:45"); if (ts3.year() != 2024 || ts3.month() != 6 || ts3.day() != 15) { pass = false; fail_msg = "String constructor parse failed"; } .. _example-timestamp-normalize-53: .. dropdown:: normalize (pd_test_1_all.cpp:8723) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 8713 :emphasize-lines: 11 void pd_test_datetime_mixin_normalize() { std::cout << "========= normalize ==================================="; // Create datetime with time component std::vector> values = { numpy::datetime64(86400000000000LL + 3600000000000LL, numpy::DateTimeUnit::Nanosecond) // 1 day + 1 hour }; pandas::DatetimeArray arr(values); pandas::DatetimeMixinIndex idx(arr); pandas::DatetimeMixinIndex normalized = idx.normalize(); bool passed = (normalized.size() == 1); if (!passed) { std::cout << " [FAIL] : in pd_test_datetime_mixin_normalize()" << std::endl; throw std::runtime_error("pd_test_datetime_mixin_normalize failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-now-54: .. dropdown:: now (pd_test_3_all.cpp:20077) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 20067 :emphasize-lines: 11 bool passed = months_default[0] == "June" && days_default[0] == "Monday"; if (!passed) { std::cout << " [FAIL] : in pd_test_name_locale_params()" << std::endl; throw std::runtime_error("pd_test_name_locale_params failed"); } std::cout << " -> tests passed" << std::endl; } // ============================================================================ // Test Period.now() with tz parameter // ============================================================================ void pd_test_period_now_tz() { std::cout << "========= Period.now(tz) ================================"; // Test now() with default (local time) auto p_local = pandas::Period::now("D"); // Test now() with UTC timezone auto p_utc = pandas::Period::now("D", "UTC"); .. _example-timestamp-quarter-55: .. dropdown:: quarter (pd_test_1_all.cpp:1218) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1208 :emphasize-lines: 11 void pd_test_datetime_array_quarter() { std::cout << "========= DatetimeArray: quarter ======================= "; pandas::DatetimeArray arr(std::vector{ "2023-01-15", // Q1 "2023-05-20", // Q2 "2023-09-10", // Q3 "2023-11-25" // Q4 }); auto quarters = arr.quarter(); auto q0 = quarters[0]; if (!q0.has_value() || q0.value() != 1) { std::cout << " [FAIL] : quarter[0] should be 1" << std::endl; throw std::runtime_error("pd_test_datetime_array_quarter failed: quarter[0]"); } auto q1 = quarters[1]; if (!q1.has_value() || q1.value() != 2) { std::cout << " [FAIL] : quarter[1] should be 2" << std::endl; throw std::runtime_error("pd_test_datetime_array_quarter failed: quarter[1]"); .. _example-timestamp-result-56: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-57: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-58: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-59: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-60: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-61: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-62: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-63: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-64: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-65: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-result-66: .. dropdown:: result (pd_test_1_all.cpp:15406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 15396 :emphasize-lines: 11 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond)); data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond)); numpy::NDArray mask(std::vector{2}); mask.setElementAt({0}, numpy::bool_(false)); mask.setElementAt({1}, numpy::bool_(false)); pandas::DatetimeArray arr(data, mask); pandas::DatetimeIndexBase idx(arr, "original"); // Create join result (int64 values) numpy::NDArray join_result(std::vector{3}); join_result.setElementAt({0}, numpy::int64(500LL)); join_result.setElementAt({1}, numpy::int64(600LL)); join_result.setElementAt({2}, numpy::int64(700LL)); auto new_idx = idx._from_join_target(join_result); bool passed = (new_idx.size() == 3 && new_idx.name().has_value() && *new_idx.name() == "original"); if (!passed) { .. _example-timestamp-round-67: .. dropdown:: round (pd_test_1_all.cpp:1688) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1678 :emphasize-lines: 11 void pd_test_floating_array_rounding() { std::cout << "========= FloatingArray: rounding ======================= "; pandas::FloatingArray arr({ std::optional(1.234), std::optional(2.567), std::nullopt }); auto rounded = arr.round(2); if (std::abs(rounded[0].value() - 1.23) > 0.001 || std::abs(rounded[1].value() - 2.57) > 0.001) { std::cout << " [FAIL] : in pd_test_floating_array_rounding() : round(2)" << std::endl; throw std::runtime_error("pd_test_floating_array_rounding failed: round(2)"); } if (!rounded.is_na(2)) { std::cout << " [FAIL] : in pd_test_floating_array_rounding() : round should preserve NA" << std::endl; throw std::runtime_error("pd_test_floating_array_rounding failed: NA preservation"); } .. _example-timestamp-second-68: .. dropdown:: second (pd_test_1_all.cpp:7534) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 7524 :emphasize-lines: 11 std::cout << "========= second property ============================="; std::vector> values = { make_dt(0), // Second 0 make_dt(30 * NS_PER_SEC), // Second 30 make_dt(59 * NS_PER_SEC) // Second 59 }; pandas::DatetimeArray arr(values); pandas::DatetimeIndex idx(arr); auto seconds = idx.second(); bool passed = (seconds.size() == 3); auto s0 = seconds[0]; auto s1 = seconds[1]; auto s2 = seconds[2]; passed = passed && s0.has_value() && *s0 == 0; passed = passed && s1.has_value() && *s1 == 30; passed = passed && s2.has_value() && *s2 == 59; if (!passed) { .. _example-timestamp-settimezone-69: .. dropdown:: setTimezone (pd_test_3_all.cpp:25427) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 25417 :emphasize-lines: 11 void pd_test_dst_offset_spring_forward() { std::cout << "========= apply_offset_dst_aware: spring forward ======="; auto tz = numpy::getTimezone("US/Eastern"); if (!tz) { std::cout << " -> skipped (timezone not available)" << std::endl; return; } // March 11, 2023 12:00 EST = 17:00 UTC int64_t utc_ns = pandas::Timestamp::componentsToNanos(2023, 3, 11, 17, 0, 0, 0, 0); pandas::Timestamp ts(utc_ns, ""); ts.setTimezone(tz); pandas::DateOffset off(1, false, 0, 0, 0, 1); // +1 day auto result = pandas::datetime_utils::apply_offset_dst_aware(off, ts); if (!result.timezone()) throw std::runtime_error("apply_offset DST: timezone lost"); std::cout << " -> tests passed" << std::endl; } void pd_test_dst_offset_naive_stays_naive() { std::cout << "========= apply_offset_dst_aware: naive stays naive ===="; int64_t ns = pandas::Timestamp::componentsToNanos(2023, 1, 1, 0, 0, 0, 0, 0); .. _example-timestamp-ss-70: .. dropdown:: ss (pd_test_3_all.cpp:27670) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 27660 :emphasize-lines: 11 fail++; } else { auto cats = str_s->get_cat_categories(); if (cats.size() != 3) { std::cout << " FAIL: expected 3 categories, got " << cats.size() << std::endl; fail++; } } } pandas::Series ss({"a", "b", "a", "c"}, "strs"); auto result2 = ss.astype("category"); auto* str_s2 = dynamic_cast*>(result2.get()); if (!str_s2) { std::cout << " FAIL: expected Series for string->category" << std::endl; fail++; } else { if (str_s2->dtype_name() != "category") { std::cout << " FAIL: dtype should be category" << std::endl; fail++; } .. _example-timestamp-strftime-71: .. dropdown:: strftime (pd_test_1_all.cpp:8434) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 8424 :emphasize-lines: 11 void pd_test_datetime_mixin_strftime() { std::cout << "========= strftime ===================================="; std::vector> values = { numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond), // 1970-01-01 numpy::datetime64(86400000000000LL, numpy::DateTimeUnit::Nanosecond) // 1970-01-02 }; pandas::DatetimeArray arr(values); pandas::DatetimeMixinIndex idx(arr); std::vector formatted = idx.strftime("%Y-%m-%d"); bool passed = (formatted.size() == 2 && !formatted[0].empty() && !formatted[1].empty()); if (!passed) { std::cout << " [FAIL] : in pd_test_datetime_mixin_strftime()" << std::endl; throw std::runtime_error("pd_test_datetime_mixin_strftime failed"); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-strptime-72: .. dropdown:: strptime (pd_test_timestamp_scalar.cpp:280) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 270 :emphasize-lines: 11 threw = true; } if (!threw) { throw std::runtime_error("fromisoformat failed: should throw for too short string"); } std::cout << " -> tests passed" << std::endl; } void np_test_timestamp_strptime() { std::cout << "========= Timestamp::strptime() ======================="; // Test 1: Basic date parsing pandas::Timestamp ts1 = pandas::Timestamp::strptime("2024-03-15", "%Y-%m-%d"); if (ts1.year() != 2024 || ts1.month() != 3 || ts1.day() != 15) { throw std::runtime_error("strptime failed: basic date parsing"); } // Test 2: Date and time parsing pandas::Timestamp ts2 = pandas::Timestamp::strptime("2024-03-15 14:30:45", "%Y-%m-%d %H:%M:%S"); if (ts2.year() != 2024 || ts2.month() != 3 || ts2.day() != 15 || .. _example-timestamp-time-73: .. dropdown:: time (pd_test_timestamp_scalar.cpp:535) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 525 :emphasize-lines: 11 if (posix <= 0) { pass = false; fail_msg = "POSIX timestamp should be positive"; } // timetuple auto [y, mo, d, h, mi, s] = ts.timetuple(); if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; } // date/time tuples auto [dy, dm, dd] = ts.date(); if (dy != 2024) { pass = false; fail_msg = "date tuple year"; } auto [th, tmi, ts2, tus] = ts.time(); if (th != 12) { pass = false; fail_msg = "time tuple hour"; } // Julian date double jd = ts.to_julian_date(); if (jd < 2400000) { pass = false; fail_msg = "Julian date should be reasonable"; } // Ordinal int ord = ts.toordinal(); if (ord <= 0) { pass = false; fail_msg = "Ordinal should be positive"; } .. _example-timestamp-timestamp-74: .. dropdown:: timestamp (pd_test_2_all.cpp:16572) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 16562 :emphasize-lines: 11 pandas::DataFrame df(data); df.set_index(std::make_unique(period_idx)); // Verify it's a PeriodIndex const pandas::PeriodIndex* pidx = dynamic_cast(&df.index()); if (!pidx) { std::cout << " [FAIL] : in pd_test_to_timestamp_basic() : index is not PeriodIndex" << std::endl; throw std::runtime_error("pd_test_to_timestamp_basic failed: index is not PeriodIndex"); } // Convert to timestamp (start of period - default) pandas::DataFrame df_start = df.to_timestamp(); // Verify it's now a DatetimeIndex const pandas::DatetimeIndex* dtidx = dynamic_cast(&df_start.index()); if (!dtidx) { std::cout << " [FAIL] : in pd_test_to_timestamp_basic() : result index is not DatetimeIndex" << std::endl; throw std::runtime_error("pd_test_to_timestamp_basic failed: result index is not DatetimeIndex"); } // Verify data is preserved .. _example-timestamp-timetuple-75: .. dropdown:: timetuple (pd_test_timestamp_scalar.cpp:528) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 518 :emphasize-lines: 11 // to_pydatetime std::tm tm = ts.to_pydatetime(); if (tm.tm_year != 124) { pass = false; fail_msg = "tm_year should be 124 (2024-1900)"; } if (tm.tm_mon != 5) { pass = false; fail_msg = "tm_mon should be 5 (June)"; } // timestamp double posix = ts.timestamp(); if (posix <= 0) { pass = false; fail_msg = "POSIX timestamp should be positive"; } // timetuple auto [y, mo, d, h, mi, s] = ts.timetuple(); if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; } // date/time tuples auto [dy, dm, dd] = ts.date(); if (dy != 2024) { pass = false; fail_msg = "date tuple year"; } auto [th, tmi, ts2, tus] = ts.time(); if (th != 12) { pass = false; fail_msg = "time tuple hour"; } // Julian date .. _example-timestamp-timetz-76: .. dropdown:: timetz (pd_test_timestamp_scalar.cpp:1042) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1032 :emphasize-lines: 11 // Test 3: utctimetuple() - returns (year, month, day, hour, minute, second) in UTC pandas::Timestamp ts_utc(2024, 6, 15, 14, 30, 45, 0, 0, "UTC"); auto utc_tuple = ts_utc.utctimetuple(); if (pass && std::get<0>(utc_tuple) != 2024) { pass = false; fail_msg = "utctimetuple year mismatch"; } if (pass && std::get<1>(utc_tuple) != 6) { pass = false; fail_msg = "utctimetuple month mismatch"; } if (pass && std::get<2>(utc_tuple) != 15) { pass = false; fail_msg = "utctimetuple day mismatch"; } if (pass && std::get<3>(utc_tuple) != 14) { pass = false; fail_msg = "utctimetuple hour mismatch"; } if (pass && std::get<4>(utc_tuple) != 30) { pass = false; fail_msg = "utctimetuple minute mismatch"; } if (pass && std::get<5>(utc_tuple) != 45) { pass = false; fail_msg = "utctimetuple second mismatch"; } // Test 4: timetz() - returns (hour, minute, second, microsecond, tz_offset_seconds) pandas::Timestamp ts_tz(2024, 6, 15, 14, 30, 45, 123456, 0, "UTC"); auto time_tuple = ts_tz.timetz(); if (pass && std::get<0>(time_tuple) != 14) { pass = false; fail_msg = "timetz hour mismatch"; } if (pass && std::get<1>(time_tuple) != 30) { pass = false; fail_msg = "timetz minute mismatch"; } if (pass && std::get<2>(time_tuple) != 45) { pass = false; fail_msg = "timetz second mismatch"; } if (pass && std::get<3>(time_tuple) != 123456) { pass = false; fail_msg = "timetz microsecond mismatch"; } // UTC offset should be 0 for UTC timezone if (pass && std::get<4>(time_tuple) != 0) { pass = false; fail_msg = "timetz UTC offset should be 0, got " + std::to_string(std::get<4>(time_tuple)); } if (!pass) { .. _example-timestamp-timezone-77: .. dropdown:: timezone (pd_test_2_all.cpp:17898) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 17888 :emphasize-lines: 11 // Use UTC timestamps and localize to a timezone first std::vector> datetimes; // 2018-09-15 05:30:00 UTC = 1537076200 seconds since epoch datetimes.push_back(numpy::datetime64(1537076200000000000LL, numpy::DateTimeUnit::Nanosecond)); // 2018-09-16 05:30:00 UTC datetimes.push_back(numpy::datetime64(1537162600000000000LL, numpy::DateTimeUnit::Nanosecond)); pandas::DatetimeArray dt_arr(datetimes); pandas::DatetimeIndex dt_idx(dt_arr, "timestamp"); // Localize to US/Eastern timezone (timezone-aware) pandas::DatetimeIndex tz_aware_idx = dt_idx.tz_localize("US/Eastern"); // Create DataFrame with timezone-aware DatetimeIndex std::map> data; data["value"] = {1.0, 2.0}; pandas::DataFrame df(data); df.set_index(std::make_unique(tz_aware_idx)); // Verify the index is timezone-aware const pandas::DatetimeIndex* original_idx = dynamic_cast(&df.index()); .. _example-timestamp-tostring-78: .. dropdown:: toString (pd_test_1_all.cpp:9539) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 9529 :emphasize-lines: 11 void pd_test_timedelta_rounding_params() { std::cout << "========= Timedelta rounding with DST params ====="; // Create a Timedelta: 1h 30m 45s // Constructor is: (days, hours, minutes, seconds, ...) pandas::Timedelta td(0, 1, 30, 45); // 0 days, 1h, 30m, 45s // Test floor with ambiguous/nonexistent params pandas::Timedelta floored = td.floor("h", "raise", "raise"); std::cout << std::endl << " floor('h'): " << floored.toString(); // Test ceil with ambiguous/nonexistent params pandas::Timedelta ceiled = td.ceil("h", "raise", "raise"); std::cout << std::endl << " ceil('h'): " << ceiled.toString(); // Test round with ambiguous/nonexistent params pandas::Timedelta rounded = td.round("h", "raise", "raise"); std::cout << std::endl << " round('h'): " << rounded.toString(); // Verify results: .. _example-timestamp-today-79: .. dropdown:: today (pd_test_5_all.cpp:108359) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 108349 :emphasize-lines: 11 auto spec = get_fill_spec(row.fill_kind); // patch 3 (Int64/boolean/string nullable-extension): route through the // nullable runner so dtype_override_ is set BEFORE reindex_with_spec. if (row.storage == "Int64") return run_nullable_int64({10, 20, 30}, new_idx, spec); if (row.storage == "boolean") return run_nullable_bool({true, false, true}, new_idx, spec); if (row.storage == "string_ea") return run_nullable_string({"x", "y", "z"}, new_idx, spec); // patch 4 (Series): no instantiation today (see plan body // for the extern-template prescription). Signal a SKIP up the chain so // the row is counted as deferred, not failed. The marker uses the same // :F16_NOT_INSTANTIATED contract that check_row's SKIP branch // recognises. if (row.storage == "float16") throw std::runtime_error("F16_NOT_INSTANTIATED: see plan patch 4"); // Phase-3B nullable-extension storages — no PandasCore constructor today // (add_column_nullable only specialises for int64_t/bool/std::string at // pd_dataframe.h:5946-5947). When Phase-3B lands, replace these throws .. _example-timestamp-toordinal-80: .. dropdown:: toordinal (pd_test_timestamp_scalar.cpp:543) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 533 :emphasize-lines: 11 if (dy != 2024) { pass = false; fail_msg = "date tuple year"; } auto [th, tmi, ts2, tus] = ts.time(); if (th != 12) { pass = false; fail_msg = "time tuple hour"; } // Julian date double jd = ts.to_julian_date(); if (jd < 2400000) { pass = false; fail_msg = "Julian date should be reasonable"; } // Ordinal int ord = ts.toordinal(); if (ord <= 0) { pass = false; fail_msg = "Ordinal should be positive"; } if (!pass) { std::cout << " [FAIL] : in np_test_timestamp_conversions() : " << fail_msg; throw std::runtime_error("np_test_timestamp_conversions failed: " + fail_msg); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-tz-81: .. dropdown:: tz (pd_test_2_all.cpp:17914) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 17904 :emphasize-lines: 11 pandas::DataFrame df(data); df.set_index(std::make_unique(tz_aware_idx)); // Verify the index is timezone-aware const pandas::DatetimeIndex* original_idx = dynamic_cast(&df.index()); if (!original_idx) { std::cout << " [FAIL] : in pd_test_tz_convert_basic() : index is not DatetimeIndex" << std::endl; throw std::runtime_error("pd_test_tz_convert_basic failed: index is not DatetimeIndex"); } std::string original_tz = original_idx->tz(); if (original_tz.empty()) { std::cout << " [FAIL] : in pd_test_tz_convert_basic() : original index is not timezone-aware" << std::endl; throw std::runtime_error("pd_test_tz_convert_basic failed: original index is not timezone-aware"); } // Convert to Asia/Shanghai timezone pandas::DataFrame df_shanghai = df.tz_convert("Asia/Shanghai"); // Verify result has a DatetimeIndex const pandas::DatetimeIndex* converted_idx = dynamic_cast(&df_shanghai.index()); .. _example-timestamp-tzinfo-82: .. dropdown:: tzinfo (pd_test_timestamp_scalar.cpp:473) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 463 :emphasize-lines: 11 void np_test_timestamp_timezone() { std::cout << "========= timestamp: timezone properties ========================="; auto pass = true; std::string fail_msg; // Naive timestamp pandas::Timestamp naive(2024, 6, 15); if (!naive.tz().empty()) { pass = false; fail_msg = "Naive should have empty tz"; } if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; } // UTC timestamp pandas::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC"); if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; } if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; } // Named timezone pandas::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York"); if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; } std::string tzname = ny.tzname(); .. _example-timestamp-tzname-83: .. dropdown:: tzname (pd_test_timestamp_scalar.cpp:483) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 473 :emphasize-lines: 11 if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; } // UTC timestamp pandas::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC"); if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; } if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; } // Named timezone pandas::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York"); if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; } std::string tzname = ny.tzname(); if (tzname != "EDT" && tzname != "EST") { pass = false; fail_msg = "Summer should be EDT or EST"; } if (!pass) { std::cout << " [FAIL] : in np_test_timestamp_timezone() : " << fail_msg; throw std::runtime_error("np_test_timestamp_timezone failed: " + fail_msg); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-utcfromtimestamp-84: .. dropdown:: utcfromtimestamp (pd_test_timestamp_scalar.cpp:1020) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1010 :emphasize-lines: 11 } if (pass && ts_from_nanos.month() != 6) { pass = false; fail_msg = "Timestamp(int64_t) month should be 6, got " + std::to_string(ts_from_nanos.month()); } if (pass && ts_from_nanos.day() != 15) { pass = false; fail_msg = "Timestamp(int64_t) day should be 15, got " + std::to_string(ts_from_nanos.day()); } // Test 2: utcfromtimestamp(double ts) - creates UTC timestamp from POSIX timestamp // 1718454645.0 = 2024-06-15 12:30:45 UTC (verified with Python) double posix_ts = 1718454645.0; pandas::Timestamp utc_ts = pandas::Timestamp::utcfromtimestamp(posix_ts); if (pass && utc_ts.year() != 2024) { pass = false; fail_msg = "utcfromtimestamp year mismatch, got " + std::to_string(utc_ts.year()); } if (pass && utc_ts.month() != 6) { pass = false; fail_msg = "utcfromtimestamp month mismatch, got " + std::to_string(utc_ts.month()); } if (pass && utc_ts.day() != 15) { pass = false; fail_msg = "utcfromtimestamp day mismatch, got " + std::to_string(utc_ts.day()); } if (pass && utc_ts.hour() != 12) { pass = false; fail_msg = "utcfromtimestamp hour mismatch, got " + std::to_string(utc_ts.hour()); } if (pass && utc_ts.minute() != 30) { pass = false; fail_msg = "utcfromtimestamp minute mismatch, got " + std::to_string(utc_ts.minute()); } if (pass && utc_ts.second() != 45) { pass = false; fail_msg = "utcfromtimestamp second mismatch, got " + std::to_string(utc_ts.second()); } if (pass && utc_ts.tz() != "UTC") { pass = false; fail_msg = "utcfromtimestamp should have UTC timezone, got '" + utc_ts.tz() + "'"; } .. _example-timestamp-utcnow-85: .. dropdown:: utcnow (pd_test_timestamp_scalar.cpp:103) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 93 :emphasize-lines: 11 fail_msg = "now() should not return NaT"; } // today() pandas::Timestamp today = pandas::Timestamp::today(); if (today.hour() != 0 || today.minute() != 0 || today.second() != 0) { pass = false; fail_msg = "today() should be at midnight"; } // utcnow() pandas::Timestamp utcnow = pandas::Timestamp::utcnow(); if (utcnow.isNaT() || utcnow.tz() != "UTC") { pass = false; fail_msg = "utcnow() should have UTC timezone"; } // fromtimestamp - Unix epoch pandas::Timestamp epoch = pandas::Timestamp::fromtimestamp(0.0); if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) { pass = false; .. _example-timestamp-utcoffset-86: .. dropdown:: utcoffset (pd_test_timestamp_scalar.cpp:765) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 755 :emphasize-lines: 11 } // astimezone (alias) pandas::Timestamp ast = localized.astimezone("UTC"); if (ast.tz() != "UTC") { pass = false; fail_msg = "astimezone should convert to UTC"; } // utcoffset numpy::timedelta64 offset = localized.utcoffset(); if (offset.isNaT()) { pass = false; fail_msg = "utcoffset should not be NaT"; } // dst numpy::timedelta64 dst_val = localized.dst(); if (dst_val.isNaT()) { pass = false; fail_msg = "dst should not be NaT"; .. _example-timestamp-utctimetuple-87: .. dropdown:: utctimetuple (pd_test_timestamp_scalar.cpp:1032) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1022 :emphasize-lines: 11 double posix_ts = 1718454645.0; pandas::Timestamp utc_ts = pandas::Timestamp::utcfromtimestamp(posix_ts); if (pass && utc_ts.year() != 2024) { pass = false; fail_msg = "utcfromtimestamp year mismatch, got " + std::to_string(utc_ts.year()); } if (pass && utc_ts.month() != 6) { pass = false; fail_msg = "utcfromtimestamp month mismatch, got " + std::to_string(utc_ts.month()); } if (pass && utc_ts.day() != 15) { pass = false; fail_msg = "utcfromtimestamp day mismatch, got " + std::to_string(utc_ts.day()); } if (pass && utc_ts.hour() != 12) { pass = false; fail_msg = "utcfromtimestamp hour mismatch, got " + std::to_string(utc_ts.hour()); } if (pass && utc_ts.minute() != 30) { pass = false; fail_msg = "utcfromtimestamp minute mismatch, got " + std::to_string(utc_ts.minute()); } if (pass && utc_ts.second() != 45) { pass = false; fail_msg = "utcfromtimestamp second mismatch, got " + std::to_string(utc_ts.second()); } if (pass && utc_ts.tz() != "UTC") { pass = false; fail_msg = "utcfromtimestamp should have UTC timezone, got '" + utc_ts.tz() + "'"; } // Test 3: utctimetuple() - returns (year, month, day, hour, minute, second) in UTC pandas::Timestamp ts_utc(2024, 6, 15, 14, 30, 45, 0, 0, "UTC"); auto utc_tuple = ts_utc.utctimetuple(); if (pass && std::get<0>(utc_tuple) != 2024) { pass = false; fail_msg = "utctimetuple year mismatch"; } if (pass && std::get<1>(utc_tuple) != 6) { pass = false; fail_msg = "utctimetuple month mismatch"; } if (pass && std::get<2>(utc_tuple) != 15) { pass = false; fail_msg = "utctimetuple day mismatch"; } if (pass && std::get<3>(utc_tuple) != 14) { pass = false; fail_msg = "utctimetuple hour mismatch"; } if (pass && std::get<4>(utc_tuple) != 30) { pass = false; fail_msg = "utctimetuple minute mismatch"; } if (pass && std::get<5>(utc_tuple) != 45) { pass = false; fail_msg = "utctimetuple second mismatch"; } // Test 4: timetz() - returns (hour, minute, second, microsecond, tz_offset_seconds) .. _example-timestamp-value-88: .. dropdown:: value (pd_test_1_all.cpp:88) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 78 :emphasize-lines: 11 // T & T = T, T & F = F, T & NA = NA // F & T = F, F & F = F, F & NA = F (False dominates) // NA & T = NA, NA & F = F, NA & NA = NA pandas::BooleanArray t({std::optional(true)}); pandas::BooleanArray f({std::optional(false)}); pandas::BooleanArray na({std::nullopt}); // T & T = T auto tt = (t & t); if (!tt[0].has_value() || !tt[0].value()) { std::cout << " [FAIL] : in pd_test_boolean_array_kleene_and() : T & T should be T" << std::endl; throw std::runtime_error("pd_test_boolean_array_kleene_and failed: T & T"); } // T & F = F auto tf = (t & f); if (!tf[0].has_value() || tf[0].value()) { std::cout << " [FAIL] : in pd_test_boolean_array_kleene_and() : T & F should be F" << std::endl; throw std::runtime_error("pd_test_boolean_array_kleene_and failed: T & F"); } .. _example-timestamp-week-89: .. dropdown:: week (pd_test_timestamp_scalar.cpp:406) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 396 :emphasize-lines: 11 // 2024-06-15 is a Saturday pandas::Timestamp ts(2024, 6, 15); if (ts.dayofweek() != 5) { pass = false; fail_msg = "2024-06-15 should be Saturday (5)"; } if (ts.day_of_week() != 5) { pass = false; fail_msg = "day_of_week alias"; } if (ts.dayofyear() != 167) { pass = false; fail_msg = "2024-06-15 should be day 167"; } if (ts.day_of_year() != 167) { pass = false; fail_msg = "day_of_year alias"; } if (ts.quarter() != 2) { pass = false; fail_msg = "June is Q2"; } if (ts.days_in_month() != 30) { pass = false; fail_msg = "June has 30 days"; } int week = ts.week(); if (week < 1 || week > 53) { pass = false; fail_msg = "week should be 1-53"; } if (!pass) { std::cout << " [FAIL] : in np_test_timestamp_derived() : " << fail_msg; throw std::runtime_error("np_test_timestamp_derived failed: " + fail_msg); } std::cout << " -> tests passed" << std::endl; } .. _example-timestamp-weekday-90: .. dropdown:: weekday (pd_test_3_all.cpp:1471) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1461 :emphasize-lines: 11 std::cout << " [FAIL] date_range 10-arg form: expected size 10, got " << idx.size() << std::endl; throw std::runtime_error("date_range 10-arg form regressed"); } } std::cout << " -> tests passed" << std::endl; } void pd_test_3_all_period_weekday() { std::cout << "========= PeriodArray.weekday() ======================"; // Create a PeriodArray with some dates std::vector> ordinals = {0, 1, 2, 3, 4}; // Days from epoch pandas::PeriodArray arr(ordinals, "D"); pandas::IntegerArray weekdays = arr.weekday(); if (weekdays.size() != 5) { std::cout << " [FAIL] : in pd_test_3_all_period_weekday() : size should be 5" << std::endl; throw std::runtime_error("pd_test_3_all_period_weekday failed: size"); .. _example-timestamp-year-91: .. dropdown:: year (pd_test_1_all.cpp:1147) :class-title: example-dropdown .. code-block:: cpp :linenos: :lineno-start: 1137 :emphasize-lines: 11 void pd_test_datetime_array_component_year() { std::cout << "========= DatetimeArray: year component ======================= "; pandas::DatetimeArray arr(std::vector{ "2020-01-15", "NaT", "2025-06-20" }); auto years = arr.year(); auto y0 = years[0]; if (!y0.has_value() || y0.value() != 2020) { std::cout << " [FAIL] : year[0] should be 2020" << std::endl; throw std::runtime_error("pd_test_datetime_array_component_year failed: year[0]"); } auto y1 = years[1]; if (y1.has_value()) { std::cout << " [FAIL] : year[1] should be NA (NaT)" << std::endl;