Timestamp#
-
class pandas::Timestamp#
pandas C++ class.
Example#
#include <pandas/pandas.h>
using namespace pandas;
// Use Timestamp
Timestamp obj;
// ... operations ...
Constructors#
Signature |
Location |
Example |
|---|---|---|
|
pd_timestamp.h:158 |
|
|
pd_timestamp.h:215 |
|
|
pd_timestamp.h:449 |
|
|
pd_timestamp.h:468 |
Data Manipulation#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
Timestamp |
pd_timestamp.h:1427 |
Statistics#
Comparison#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
Timestamp |
pd_timestamp.h:1286 |
Combining#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
static Timestamp |
pd_timestamp.h:535 |
Time Series#
I/O#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
numpy::datetime64 |
pd_timestamp.h:1018 |
|
|
double |
pd_timestamp.h:1103 |
|
|
int64_t |
pd_timestamp.h:1032 |
|
|
std::tm |
pd_timestamp.h:1039 |
Type Checking#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
bool |
pd_timestamp.h:941 |
|
|
bool |
pd_timestamp.h:953 |
|
|
bool |
pd_timestamp.h:947 |
|
|
bool |
pd_timestamp.h:965 |
|
|
bool |
pd_timestamp.h:959 |
|
|
bool |
pd_timestamp.h:977 |
|
|
bool |
pd_timestamp.h:971 |
Other Methods#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
static Timestamp |
pd_timestamp.h:805 |
|
|
Timestamp |
pd_timestamp.h:1458 |
|
|
numpy::datetime64 |
pd_timestamp.h:1024 |
|
|
Timestamp |
pd_timestamp.h:1539 |
|
|
Timestamp |
pd_timestamp.h:1348 |
|
|
static int64_t |
pd_timestamp.h:40 |
|
|
void |
pd_timestamp.h:92 |
|
|
std::string |
pd_timestamp.h:1212 |
|
|
std::tuple<int,int,int> |
pd_timestamp.h:1081 |
|
|
int |
pd_timestamp.h:833 |
|
|
std::string |
pd_timestamp.h:1217 |
|
|
int |
pd_timestamp.h:895 |
|
|
int |
pd_timestamp.h:912 |
|
|
int |
pd_timestamp.h:878 |
|
|
int |
pd_timestamp.h:898 |
|
|
int |
pd_timestamp.h:931 |
|
|
numpy::timedelta64 |
pd_timestamp.h:1553 |
|
|
static int64_t |
pd_timestamp.h:505 |
|
|
Timestamp |
pd_timestamp.h:1320 |
|
|
int |
pd_timestamp.h:1009 |
|
|
static Timestamp |
pd_timestamp.h:544 |
|
|
static Timestamp |
pd_timestamp.h:574 |
|
|
static Timestamp |
pd_timestamp.h:526 |
|
|
static Timestamp |
pd_timestamp.h:515 |
|
|
int |
pd_timestamp.h:839 |
|
|
void |
pd_timestamp.h:88 |
|
|
bool |
pd_timestamp.h:813 |
|
|
std::tuple<int,int,int> |
pd_timestamp.h:1241 |
|
|
std::string |
pd_timestamp.h:1153 |
|
|
int |
pd_timestamp.h:1300 |
|
|
Timestamp |
pd_timestamp.h:555 |
|
|
Timestamp |
pd_timestamp.h:1263 |
|
|
int |
pd_timestamp.h:857 |
|
|
int |
pd_timestamp.h:827 |
|
|
std::string |
pd_timestamp.h:1225 |
|
|
int |
pd_timestamp.h:863 |
|
|
Timestamp |
pd_timestamp.h:1405 |
|
|
static Timestamp |
pd_timestamp.h:486 |
|
|
static int64_t |
pd_timestamp.h:136 |
|
|
Timestamp |
pd_timestamp.h:1278 |
|
|
int |
pd_timestamp.h:924 |
|
|
Timestamp |
pd_timestamp.h:1335 |
|
|
Timestamp |
pd_timestamp.h:1366 |
|
|
Timestamp |
pd_timestamp.h:1399 |
|
|
Timestamp |
pd_timestamp.h:1476 |
|
|
Timestamp |
pd_timestamp.h:1510 |
|
|
Timestamp |
pd_timestamp.h:1526 |
|
|
Timestamp |
pd_timestamp.h:1533 |
|
|
Timestamp |
pd_timestamp.h:1581 |
|
|
Timestamp |
pd_timestamp.h:1595 |
|
|
Timestamp |
pd_timestamp.h:1628 |
|
|
Timestamp |
pd_timestamp.h:1640 |
|
|
Timestamp |
pd_timestamp.h:1379 |
|
|
int |
pd_timestamp.h:851 |
|
|
void |
pd_timestamp.h:997 |
|
|
std::istringstream |
pd_timestamp.h:392 |
|
|
std::string |
pd_timestamp.h:1203 |
|
|
static Timestamp |
pd_timestamp.h:601 |
|
|
Timestamp |
pd_timestamp.h:1257 |
|
|
std::tuple<int,int,int,int> |
pd_timestamp.h:1088 |
|
|
double |
pd_timestamp.h:1058 |
|
|
std::tuple<int,int,int,int,int,int> |
pd_timestamp.h:1064 |
|
|
std::tuple<int,int,int,int,int> |
pd_timestamp.h:1095 |
|
|
std::shared_ptr<numpy::TimezoneInfo> |
pd_timestamp.h:995 |
|
|
std::string |
pd_timestamp.h:1130 |
|
|
std::string |
pd_timestamp.h:1147 |
|
|
static Timestamp |
pd_timestamp.h:494 |
|
|
int |
pd_timestamp.h:1112 |
|
|
std::string |
pd_timestamp.h:987 |
|
|
std::string |
pd_timestamp.h:991 |
|
|
std::string |
pd_timestamp.h:1002 |
|
|
std::string |
pd_timestamp.h:1004 |
|
|
Timestamp |
pd_timestamp.h:1074 |
|
|
static Timestamp |
pd_timestamp.h:521 |
|
|
static Timestamp |
pd_timestamp.h:500 |
|
|
numpy::timedelta64 |
pd_timestamp.h:1544 |
|
|
std::tuple<int,int,int,int,int,int> |
pd_timestamp.h:1070 |
|
|
int64_t |
pd_timestamp.h:869 |
|
|
int |
pd_timestamp.h:915 |
|
|
int |
pd_timestamp.h:1305 |
|
|
int |
pd_timestamp.h:921 |
|
|
int |
pd_timestamp.h:821 |
Code Examples#
The following examples are extracted from the test suite.
Timestamp (pd_test_3_all.cpp:1501)
1491 }
1492 }
1493 }
1494
1495 std::cout << " -> tests passed" << std::endl;
1496}
1497
1498void pd_test_3_all_pandas_numpy_type_aliases() {
1499 std::cout << "========= pandas:: aliases for numpy time types =====";
1500
1501 // Case A: pandas::Timestamp == pandas::Timestamp (same type)
1502 {
1503 static_assert(std::is_same_v<pandas::Timestamp, pandas::Timestamp>,
1504 "pandas::Timestamp must alias pandas::Timestamp");
1505 pandas::Timestamp ts1("2021-01-01");
1506 pandas::Timestamp ts2("2021-01-01");
1507 // Stronger than toString()-comparison: pandas::Timestamp::operator==
1508 // compares the underlying nanosecond value directly, catching
1509 // representation drift that string formatting could mask.
1510 if (!(ts1 == ts2)) {
1511 throw std::runtime_error("alias Timestamp: ctor value mismatch");
Timestamp (pd_test_3_all.cpp:1501)
1491 }
1492 }
1493 }
1494
1495 std::cout << " -> tests passed" << std::endl;
1496}
1497
1498void pd_test_3_all_pandas_numpy_type_aliases() {
1499 std::cout << "========= pandas:: aliases for numpy time types =====";
1500
1501 // Case A: pandas::Timestamp == pandas::Timestamp (same type)
1502 {
1503 static_assert(std::is_same_v<pandas::Timestamp, pandas::Timestamp>,
1504 "pandas::Timestamp must alias pandas::Timestamp");
1505 pandas::Timestamp ts1("2021-01-01");
1506 pandas::Timestamp ts2("2021-01-01");
1507 // Stronger than toString()-comparison: pandas::Timestamp::operator==
1508 // compares the underlying nanosecond value directly, catching
1509 // representation drift that string formatting could mask.
1510 if (!(ts1 == ts2)) {
1511 throw std::runtime_error("alias Timestamp: ctor value mismatch");
Timestamp (pd_test_3_all.cpp:1501)
1491 }
1492 }
1493 }
1494
1495 std::cout << " -> tests passed" << std::endl;
1496}
1497
1498void pd_test_3_all_pandas_numpy_type_aliases() {
1499 std::cout << "========= pandas:: aliases for numpy time types =====";
1500
1501 // Case A: pandas::Timestamp == pandas::Timestamp (same type)
1502 {
1503 static_assert(std::is_same_v<pandas::Timestamp, pandas::Timestamp>,
1504 "pandas::Timestamp must alias pandas::Timestamp");
1505 pandas::Timestamp ts1("2021-01-01");
1506 pandas::Timestamp ts2("2021-01-01");
1507 // Stronger than toString()-comparison: pandas::Timestamp::operator==
1508 // compares the underlying nanosecond value directly, catching
1509 // representation drift that string formatting could mask.
1510 if (!(ts1 == ts2)) {
1511 throw std::runtime_error("alias Timestamp: ctor value mismatch");
Timestamp (pd_test_3_all.cpp:1501)
1491 }
1492 }
1493 }
1494
1495 std::cout << " -> tests passed" << std::endl;
1496}
1497
1498void pd_test_3_all_pandas_numpy_type_aliases() {
1499 std::cout << "========= pandas:: aliases for numpy time types =====";
1500
1501 // Case A: pandas::Timestamp == pandas::Timestamp (same type)
1502 {
1503 static_assert(std::is_same_v<pandas::Timestamp, pandas::Timestamp>,
1504 "pandas::Timestamp must alias pandas::Timestamp");
1505 pandas::Timestamp ts1("2021-01-01");
1506 pandas::Timestamp ts2("2021-01-01");
1507 // Stronger than toString()-comparison: pandas::Timestamp::operator==
1508 // compares the underlying nanosecond value directly, catching
1509 // representation drift that string formatting could mask.
1510 if (!(ts1 == ts2)) {
1511 throw std::runtime_error("alias Timestamp: ctor value mismatch");
replace (pd_test_1_all.cpp:6623)
6613 }
6614 }
6615
6616 // Test replace
6617 {
6618 std::map<std::string, std::vector<numpy::float64>> float_data;
6619 float_data["X"] = {1.0, 2.0, 3.0};
6620 float_data["Y"] = {2.0, 2.0, 4.0};
6621 pandas::DataFrame df_repl(float_data);
6622
6623 auto replaced = df_repl.replace(2.0, 99.0);
6624 // Check some value was replaced (crude check via string)
6625 std::string val_str = replaced.col<numpy::float64>("X").get_value_str(1);
6626 if (val_str.find("99") == std::string::npos) {
6627 std::cout << " [FAIL] : in pd_test_dataframe_manipulation() : replace didn't work" << std::endl;
6628 throw std::runtime_error("pd_test_dataframe_manipulation failed: replace");
6629 }
6630 }
6631
6632 // Test drop_duplicates
6633 {
max (pd_test_1_all.cpp:771)
761 pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true); // ordered
762
763 // Test min
764 std::optional<std::string> min_val = arr.min();
765 if (!min_val.has_value() || *min_val != "low") {
766 std::cout << " [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl;
767 throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'");
768 }
769
770 // Test max
771 std::optional<std::string> max_val = arr.max();
772 if (!max_val.has_value() || *max_val != "high") {
773 std::cout << " [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl;
774 throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'");
775 }
776
777 // Test unordered throws for min/max
778 pandas::CategoricalArray unordered = arr.as_unordered();
779 bool threw = false;
780 try {
781 unordered.min();
min (pd_test_1_all.cpp:764)
754 }
755
756 void pd_test_categorical_array_ordered_operations() {
757 std::cout << "========= CategoricalArray: ordered operations (min/max) ======================= ";
758
759 std::vector<std::string> cats = {"low", "medium", "high"};
760 std::vector<numpy::int32> codes = {0, 2, 1, 0, -1}; // low, high, medium, low, NA
761 pandas::CategoricalArray arr = pandas::CategoricalArray::from_codes(codes, cats, true); // ordered
762
763 // Test min
764 std::optional<std::string> min_val = arr.min();
765 if (!min_val.has_value() || *min_val != "low") {
766 std::cout << " [FAIL] : in pd_test_categorical_array_ordered_operations() : min != 'low'" << std::endl;
767 throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: min != 'low'");
768 }
769
770 // Test max
771 std::optional<std::string> max_val = arr.max();
772 if (!max_val.has_value() || *max_val != "high") {
773 std::cout << " [FAIL] : in pd_test_categorical_array_ordered_operations() : max != 'high'" << std::endl;
774 throw std::runtime_error("pd_test_categorical_array_ordered_operations failed: max != 'high'");
minute (pd_test_1_all.cpp:7505)
7495 std::cout << "========= minute property =============================";
7496
7497 std::vector<std::optional<numpy::datetime64>> values = {
7498 make_dt(0), // Minute 0
7499 make_dt(30 * NS_PER_MIN), // Minute 30
7500 make_dt(59 * NS_PER_MIN) // Minute 59
7501 };
7502 pandas::DatetimeArray arr(values);
7503 pandas::DatetimeIndex idx(arr);
7504
7505 auto minutes = idx.minute();
7506
7507 bool passed = (minutes.size() == 3);
7508 auto m0 = minutes[0];
7509 auto m1 = minutes[1];
7510 auto m2 = minutes[2];
7511 passed = passed && m0.has_value() && *m0 == 0;
7512 passed = passed && m1.has_value() && *m1 == 30;
7513 passed = passed && m2.has_value() && *m2 == 59;
7514
7515 if (!passed) {
combine (pd_test_2_all.cpp:1700)
1690 std::cout << "====================================== [OK] pd_test_between_time test suite ========================== " << std::endl;
1691 return 0;
1692 }
1693
1694} // namespace dataframe_tests
1695// ------------------- pd_test_between_time.cpp (end) -----------------------------
1696
1697// ------------------- pd_test_combine.cpp (start) -----------------------------
1698// dataframe_tests/pd_test_combine.cpp
1699// Test for DataFrame.combine() - column-wise combine with another DataFrame
1700
1701#include <iostream>
1702#include <cmath>
1703#include <stdexcept>
1704#include "../pandas/pd_dataframe.h"
1705
1706// CRITICAL: No using namespace directives
1707
1708namespace dataframe_tests {
1709 namespace dataframe_tests_combine {
tz_convert (pd_test_2_all.cpp:17874)
17864 std::cout << "====================================== [OK] pd_test_transform test suite ========================== " << std::endl;
17865 return 0;
17866 }
17867
17868} // namespace dataframe_tests
17869// ------------------- pd_test_transform.cpp (end) -----------------------------
17870
17871// ------------------- pd_test_tz_convert.cpp (start) -----------------------------
17872// dataframe_tests/pd_test_tz_convert.cpp
17873// Test for DataFrame.tz_convert() method
17874
17875#include <iostream>
17876#include <stdexcept>
17877#include <cmath>
17878#include "../pandas/pd_dataframe.h"
17879
17880namespace dataframe_tests {
17881 namespace dataframe_tests_tz_convert {
17882
17883 void pd_test_tz_convert_basic() {
tz_localize (pd_test_1_all.cpp:1431)
1421 "2023-06-15"
1422 });
1423
1424 // Initially should be timezone-naive
1425 if (arr.is_tz_aware()) {
1426 std::cout << " [FAIL] : array should be timezone-naive initially" << std::endl;
1427 throw std::runtime_error("pd_test_datetime_array_timezone failed: naive");
1428 }
1429
1430 // Localize to UTC
1431 auto localized = arr.tz_localize("UTC");
1432 if (!localized.is_tz_aware()) {
1433 std::cout << " [FAIL] : localized array should be timezone-aware" << std::endl;
1434 throw std::runtime_error("pd_test_datetime_array_timezone failed: localize");
1435 }
1436
1437 // Verify timezone name in dtype
1438 auto dt = localized.dtype();
1439 if (!dt.is_tz_aware()) {
1440 std::cout << " [FAIL] : dtype should be timezone-aware" << std::endl;
1441 throw std::runtime_error("pd_test_datetime_array_timezone failed: dtype tz");
to_datetime64 (pd_test_timestamp_scalar.cpp:507)
497 void np_test_timestamp_conversions() {
498 std::cout << "========= timestamp: conversion methods ==========================";
499
500 auto pass = true;
501 std::string fail_msg;
502
503 pandas::Timestamp ts(2024, 6, 15, 12, 30, 45, 123456, 789);
504
505 // to_datetime64
506 numpy::datetime64 dt = ts.to_datetime64();
507 if (dt.isNaT()) { pass = false; fail_msg = "to_datetime64 should not return NaT"; }
508
509 // asm8 alias
510 numpy::datetime64 asm8 = ts.asm8();
511 if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; }
512
513 // to_numpy
514 int64_t value = ts.to_numpy();
515 if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; }
to_julian_date (pd_test_3_all.cpp:20400)
20390// CRITICAL: No using namespace directives
20391
20392namespace dataframe_tests {
20393namespace dataframe_tests_misc {
20394
20395// ============================================================================
20396// Test DatetimeIndex.to_julian_date
20397// ============================================================================
20398
20399void pd_test_to_julian_date() {
20400 std::cout << "========= DatetimeIndex.to_julian_date() ==================";
20401
20402 // Create DatetimeIndex with known dates
20403 std::vector<std::optional<numpy::datetime64>> dates = {
20404 numpy::datetime64("2000-01-01"),
20405 numpy::datetime64("2000-01-02"),
20406 numpy::datetime64("2000-01-03")
20407 };
20408 pandas::DatetimeArray arr(dates);
20409 pandas::DatetimeIndex idx(arr, "test_dates");
to_numpy (pd_test_1_all.cpp:16764)
16754 // =====================================================================
16755 // to_numpy Tests
16756 // =====================================================================
16757
16758 void pd_test_ndframe_to_numpy() {
16759 std::cout << "========= to_numpy =============================================" << std::endl;
16760
16761 pandas::Series<int> s({10, 20, 30});
16762
16763 auto arr = s.to_numpy();
16764
16765 bool passed = arr.getSize() == 3;
16766 if (!passed) {
16767 std::cout << " [FAIL] : in pd_test_ndframe_to_numpy() : size" << std::endl;
16768 throw std::runtime_error("pd_test_ndframe_to_numpy failed: size");
16769 }
16770
16771 passed = arr.getElementAt({0}) == 10 && arr.getElementAt({1}) == 20 && arr.getElementAt({2}) == 30;
16772 if (!passed) {
16773 std::cout << " [FAIL] : in pd_test_ndframe_to_numpy() : values" << std::endl;
to_pydatetime (pd_test_timestamp_scalar.cpp:519)
509 // asm8 alias
510 numpy::datetime64 asm8 = ts.asm8();
511 if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; }
512
513 // to_numpy
514 int64_t value = ts.to_numpy();
515 if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; }
516
517 // to_pydatetime
518 std::tm tm = ts.to_pydatetime();
519 if (tm.tm_year != 124) { pass = false; fail_msg = "tm_year should be 124 (2024-1900)"; }
520 if (tm.tm_mon != 5) { pass = false; fail_msg = "tm_mon should be 5 (June)"; }
521
522 // timestamp
523 double posix = ts.timestamp();
524 if (posix <= 0) { pass = false; fail_msg = "POSIX timestamp should be positive"; }
525
526 // timetuple
527 auto [y, mo, d, h, mi, s] = ts.timetuple();
528 if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; }
is_leap_year (pd_test_1_all.cpp:1280)
1270 }
1271
1272 // is_month_end
1273 auto me = arr.is_month_end();
1274 if (!me[1].has_value() || !me[1].value()) {
1275 std::cout << " [FAIL] : 2023-03-31 should be month end" << std::endl;
1276 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month end");
1277 }
1278
1279 // is_leap_year
1280 auto ly = arr.is_leap_year();
1281 if (!ly[2].has_value() || !ly[2].value()) {
1282 std::cout << " [FAIL] : 2024 should be leap year" << std::endl;
1283 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: leap year");
1284 }
1285 if (!ly[0].has_value() || ly[0].value()) {
1286 std::cout << " [FAIL] : 2023 should not be leap year" << std::endl;
1287 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: not leap year");
1288 }
1289
1290 std::cout << " -> tests passed" << std::endl;
is_month_end (pd_test_1_all.cpp:1273)
1263 }
1264
1265 // is_month_start
1266 auto ms = arr.is_month_start();
1267 if (!ms[0].has_value() || !ms[0].value()) {
1268 std::cout << " [FAIL] : 2023-01-01 should be month start" << std::endl;
1269 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month start");
1270 }
1271
1272 // is_month_end
1273 auto me = arr.is_month_end();
1274 if (!me[1].has_value() || !me[1].value()) {
1275 std::cout << " [FAIL] : 2023-03-31 should be month end" << std::endl;
1276 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month end");
1277 }
1278
1279 // is_leap_year
1280 auto ly = arr.is_leap_year();
1281 if (!ly[2].has_value() || !ly[2].value()) {
1282 std::cout << " [FAIL] : 2024 should be leap year" << std::endl;
1283 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: leap year");
is_month_start (pd_test_1_all.cpp:1266)
1256 if (!ys[0].has_value() || !ys[0].value()) {
1257 std::cout << " [FAIL] : 2023-01-01 should be year start" << std::endl;
1258 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: year start");
1259 }
1260 if (!ys[1].has_value() || ys[1].value()) {
1261 std::cout << " [FAIL] : 2023-03-31 should not be year start" << std::endl;
1262 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: not year start");
1263 }
1264
1265 // is_month_start
1266 auto ms = arr.is_month_start();
1267 if (!ms[0].has_value() || !ms[0].value()) {
1268 std::cout << " [FAIL] : 2023-01-01 should be month start" << std::endl;
1269 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month start");
1270 }
1271
1272 // is_month_end
1273 auto me = arr.is_month_end();
1274 if (!me[1].has_value() || !me[1].value()) {
1275 std::cout << " [FAIL] : 2023-03-31 should be month end" << std::endl;
1276 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: month end");
is_quarter_end (pd_test_3_all.cpp:25056)
25046 };
25047 pandas::Series<numpy::datetime64> s(dates);
25048 pandas::DatetimeProperties<pandas::Series<numpy::datetime64>> dt(s);
25049 if (dt.has_nat()) throw std::runtime_error("has_nat should be false for clean series");
25050 auto ms = dt.is_month_start();
25051 if (ms[0] != true || ms[1] != false) throw std::runtime_error("is_month_start failed");
25052 auto me = dt.is_month_end();
25053 if (me[1] != true || me[0] != false) throw std::runtime_error("is_month_end failed");
25054 auto qs = dt.is_quarter_start();
25055 if (qs[0] != true || qs[1] != false) throw std::runtime_error("is_quarter_start failed");
25056 auto qe = dt.is_quarter_end();
25057 if (qe[2] != true || qe[0] != false) throw std::runtime_error("is_quarter_end failed");
25058 auto ys = dt.is_year_start();
25059 if (ys[0] != true || ys[1] != false) throw std::runtime_error("is_year_start failed");
25060 auto ye = dt.is_year_end();
25061 if (ye[3] != true || ye[0] != false) throw std::runtime_error("is_year_end failed");
25062 std::cout << " -> tests passed" << std::endl;
25063}
25064
25065void pd_test_dt_bool_na_with_nat() {
25066 std::cout << "========= pd_test_dt_bool_na: series with NaT ==========";
is_quarter_start (pd_test_3_all.cpp:25054)
25044 numpy::datetime64("2024-03-31"),
25045 numpy::datetime64("2024-12-31")
25046 };
25047 pandas::Series<numpy::datetime64> s(dates);
25048 pandas::DatetimeProperties<pandas::Series<numpy::datetime64>> dt(s);
25049 if (dt.has_nat()) throw std::runtime_error("has_nat should be false for clean series");
25050 auto ms = dt.is_month_start();
25051 if (ms[0] != true || ms[1] != false) throw std::runtime_error("is_month_start failed");
25052 auto me = dt.is_month_end();
25053 if (me[1] != true || me[0] != false) throw std::runtime_error("is_month_end failed");
25054 auto qs = dt.is_quarter_start();
25055 if (qs[0] != true || qs[1] != false) throw std::runtime_error("is_quarter_start failed");
25056 auto qe = dt.is_quarter_end();
25057 if (qe[2] != true || qe[0] != false) throw std::runtime_error("is_quarter_end failed");
25058 auto ys = dt.is_year_start();
25059 if (ys[0] != true || ys[1] != false) throw std::runtime_error("is_year_start failed");
25060 auto ye = dt.is_year_end();
25061 if (ye[3] != true || ye[0] != false) throw std::runtime_error("is_year_end failed");
25062 std::cout << " -> tests passed" << std::endl;
25063}
is_year_end (pd_test_3_all.cpp:25060)
25050 auto ms = dt.is_month_start();
25051 if (ms[0] != true || ms[1] != false) throw std::runtime_error("is_month_start failed");
25052 auto me = dt.is_month_end();
25053 if (me[1] != true || me[0] != false) throw std::runtime_error("is_month_end failed");
25054 auto qs = dt.is_quarter_start();
25055 if (qs[0] != true || qs[1] != false) throw std::runtime_error("is_quarter_start failed");
25056 auto qe = dt.is_quarter_end();
25057 if (qe[2] != true || qe[0] != false) throw std::runtime_error("is_quarter_end failed");
25058 auto ys = dt.is_year_start();
25059 if (ys[0] != true || ys[1] != false) throw std::runtime_error("is_year_start failed");
25060 auto ye = dt.is_year_end();
25061 if (ye[3] != true || ye[0] != false) throw std::runtime_error("is_year_end failed");
25062 std::cout << " -> tests passed" << std::endl;
25063}
25064
25065void pd_test_dt_bool_na_with_nat() {
25066 std::cout << "========= pd_test_dt_bool_na: series with NaT ==========";
25067 std::vector<numpy::datetime64> dates = {
25068 numpy::datetime64("2024-01-01"),
25069 numpy::datetime64(), // NaT
25070 numpy::datetime64("2024-12-31")
is_year_start (pd_test_1_all.cpp:1255)
1245 std::cout << "========= DatetimeArray: boolean properties ======================= ";
1246
1247 pandas::DatetimeArray arr(std::vector<std::string>{
1248 "2023-01-01", // year start, month start
1249 "2023-03-31", // quarter end, month end
1250 "2024-02-29", // leap year (2024 is leap year)
1251 "2023-12-31" // year end, month end
1252 });
1253
1254 // is_year_start
1255 auto ys = arr.is_year_start();
1256 if (!ys[0].has_value() || !ys[0].value()) {
1257 std::cout << " [FAIL] : 2023-01-01 should be year start" << std::endl;
1258 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: year start");
1259 }
1260 if (!ys[1].has_value() || ys[1].value()) {
1261 std::cout << " [FAIL] : 2023-03-31 should not be year start" << std::endl;
1262 throw std::runtime_error("pd_test_datetime_array_boolean_props failed: not year start");
1263 }
1264
1265 // is_month_start
NaT (pd_test_1_all.cpp:1305)
1295 pandas::DatetimeArray arr(std::vector<std::string>{
1296 "2023-06-15",
1297 "NaT",
1298 "2023-01-01",
1299 "2023-12-31"
1300 });
1301
1302 // argsort ascending
1303 auto indices = arr.argsort(true, "last");
1304 // Expected order: 2023-01-01(2), 2023-06-15(0), 2023-12-31(3), NaT(1)
1305 if (indices.getElementAt({0}) != 2) {
1306 std::cout << " [FAIL] : argsort: first should be index 2 (2023-01-01)" << std::endl;
1307 throw std::runtime_error("pd_test_datetime_array_sorting failed: argsort first");
1308 }
1309 if (indices.getElementAt({3}) != 1) {
1310 std::cout << " [FAIL] : argsort: last should be index 1 (NaT)" << std::endl;
1311 throw std::runtime_error("pd_test_datetime_array_sorting failed: NaT position");
1312 }
1313
1314 // argmin
as_unit (pd_test_1_all.cpp:9361)
9351 data.setElementAt({1}, numpy::datetime64(2000000000LL, numpy::DateTimeUnit::Nanosecond)); // 2 seconds in ns
9352
9353 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
9354 mask.setElementAt({0}, numpy::bool_(false));
9355 mask.setElementAt({1}, numpy::bool_(false));
9356
9357 pandas::DatetimeArray arr(data, mask);
9358 pandas::DatetimeTDMixin idx(arr, "test");
9359
9360 // Convert to microseconds
9361 pandas::DatetimeTDMixin us_idx = idx.as_unit("us");
9362
9363 // Convert to same unit (should return identical)
9364 pandas::DatetimeTDMixin same_idx = idx.as_unit("ns");
9365
9366 bool passed = (us_idx.size() == 2 && same_idx.size() == 2 &&
9367 us_idx.name().has_value() && *us_idx.name() == "test");
9368 if (!passed) {
9369 std::cout << " [FAIL] : in pd_test_datetime_as_unit() : as_unit check failed" << std::endl;
9370 throw std::runtime_error("pd_test_datetime_as_unit failed");
9371 }
asm8 (pd_test_timestamp_scalar.cpp:511)
501 auto pass = true;
502 std::string fail_msg;
503
504 pandas::Timestamp ts(2024, 6, 15, 12, 30, 45, 123456, 789);
505
506 // to_datetime64
507 numpy::datetime64 dt = ts.to_datetime64();
508 if (dt.isNaT()) { pass = false; fail_msg = "to_datetime64 should not return NaT"; }
509
510 // asm8 alias
511 numpy::datetime64 asm8 = ts.asm8();
512 if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; }
513
514 // to_numpy
515 int64_t value = ts.to_numpy();
516 if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; }
517
518 // to_pydatetime
519 std::tm tm = ts.to_pydatetime();
520 if (tm.tm_year != 124) { pass = false; fail_msg = "tm_year should be 124 (2024-1900)"; }
521 if (tm.tm_mon != 5) { pass = false; fail_msg = "tm_mon should be 5 (June)"; }
astimezone (pd_test_timestamp_scalar.cpp:757)
747 fail_msg = "tz_localize should set timezone";
748 }
749
750 // tz_convert
751 pandas::Timestamp converted = localized.tz_convert("Europe/London");
752 if (converted.tz() != "Europe/London") {
753 pass = false;
754 fail_msg = "tz_convert should change timezone";
755 }
756
757 // astimezone (alias)
758 pandas::Timestamp ast = localized.astimezone("UTC");
759 if (ast.tz() != "UTC") {
760 pass = false;
761 fail_msg = "astimezone should convert to UTC";
762 }
763
764 // utcoffset
765 numpy::timedelta64 offset = localized.utcoffset();
766 if (offset.isNaT()) {
767 pass = false;
ceil (pd_test_1_all.cpp:4949)
4939 throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed");
4940 }
4941
4942 auto f = a.floor();
4943 passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001;
4944 if (!passed) {
4945 std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl;
4946 throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed");
4947 }
4948
4949 auto c = a.ceil();
4950 passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001;
4951 if (!passed) {
4952 std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl;
4953 throw std::runtime_error("pd_test_arithmetic_series_round failed: ceil failed");
4954 }
4955
4956 // Round with decimals
4957 pandas::Series<double> b({1.234, 2.567, 3.891});
4958 auto r2 = b.round(2);
4959 passed = std::abs(r2[0] - 1.23) < 0.001 && std::abs(r2[1] - 2.57) < 0.001;
componentsToNanos (pd_test_3_all.cpp:25149)
25139void pd_test_datetime_utils_nanos_epoch() {
25140 std::cout << "========= nanos_to_timestamp_str: epoch ================";
25141 auto result = pandas::datetime_utils::nanos_to_timestamp_str(0);
25142 if (result != "1970-01-01 00:00:00")
25143 throw std::runtime_error("nanos_to_str epoch: got " + result);
25144 std::cout << " -> tests passed" << std::endl;
25145}
25146
25147void pd_test_datetime_utils_nanos_simple() {
25148 std::cout << "========= nanos_to_timestamp_str: 2023-06-15 12:30:45 ==";
25149 int64_t ns = pandas::Timestamp::componentsToNanos(2023, 6, 15, 12, 30, 45, 0, 0);
25150 auto result = pandas::datetime_utils::nanos_to_timestamp_str(ns);
25151 if (result != "2023-06-15 12:30:45")
25152 throw std::runtime_error("nanos_to_str simple: got " + result);
25153 std::cout << " -> tests passed" << std::endl;
25154}
25155
25156void pd_test_datetime_utils_nanos_pre_epoch() {
25157 std::cout << "========= nanos_to_timestamp_str: pre-epoch 1960 =======";
25158 int64_t ns = pandas::Timestamp::componentsToNanos(1960, 1, 1, 0, 0, 0, 0, 0);
25159 auto result = pandas::datetime_utils::nanos_to_timestamp_str(ns);
ctime (pd_test_timestamp_scalar.cpp:583)
573 // isoformat with space separator
574 std::string iso_space = ts.isoformat(' ');
575 if (iso_space.find(" ") == std::string::npos) { pass = false; fail_msg = "isoformat with space separator"; }
576
577 // strftime
578 std::string fmt = ts.strftime("%Y/%m/%d");
579 if (fmt != "2024/06/15") { pass = false; fail_msg = "strftime format"; }
580
581 // ctime
582 std::string ct = ts.ctime();
583 if (ct.find("2024") == std::string::npos) { pass = false; fail_msg = "ctime should contain year"; }
584
585 // day_name
586 std::string dayname = ts.day_name();
587 if (dayname != "Saturday") { pass = false; fail_msg = "2024-06-15 is Saturday"; }
588
589 // month_name
590 std::string monthname = ts.month_name();
591 if (monthname != "June") { pass = false; fail_msg = "Month should be June"; }
date (pd_test_2_all.cpp:21549)
21539 std::cout << " -- test_pivot_grouper_mixed_plain --" << std::endl;
21540
21541 // Mix plain column and grouper
21542 auto df = make_df(
21543 {"date", "region", "product", "sales"},
21544 {{"2023-01-15", "2023-01-20", "2023-02-10", "2023-02-25"},
21545 {"East", "West", "East", "West"},
21546 {"A", "B", "A", "B"},
21547 {"100", "200", "150", "250"}});
21548
21549 // index: region (plain) + date (grouper with freq)
21550 std::vector<std::pair<std::string, std::string>> idx_groupers = {
21551 {"region", ""}, // plain column (empty freq)
21552 {"date", "ME"} // grouper with monthly freq
21553 };
21554 std::vector<std::pair<std::string, std::string>> col_groupers = {};
21555
21556 auto result = pandas::detail::pivot_table_with_grouper(
21557 df, {"sales"}, idx_groupers, col_groupers, "sum");
21558
21559 check(result.nrows() > 0, "has_rows");
day (pd_test_1_all.cpp:1193)
1183 std::cout << " [FAIL] : month[0] should be 3" << std::endl;
1184 throw std::runtime_error("pd_test_datetime_array_component_month_day failed: month[0]");
1185 }
1186 auto m1 = months[1];
1187 if (!m1.has_value() || m1.value() != 12) {
1188 std::cout << " [FAIL] : month[1] should be 12" << std::endl;
1189 throw std::runtime_error("pd_test_datetime_array_component_month_day failed: month[1]");
1190 }
1191
1192 // Day
1193 auto days = arr.day();
1194 auto d0 = days[0];
1195 if (!d0.has_value() || d0.value() != 15) {
1196 std::cout << " [FAIL] : day[0] should be 15" << std::endl;
1197 throw std::runtime_error("pd_test_datetime_array_component_month_day failed: day[0]");
1198 }
1199 auto d1 = days[1];
1200 if (!d1.has_value() || d1.value() != 25) {
1201 std::cout << " [FAIL] : day[1] should be 25" << std::endl;
1202 throw std::runtime_error("pd_test_datetime_array_component_month_day failed: day[1]");
1203 }
day_name (pd_test_1_all.cpp:8474)
8464void pd_test_datetime_mixin_day_name() {
8465 std::cout << "========= day_name ====================================";
8466
8467 std::vector<std::optional<numpy::datetime64>> values = {
8468 numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond) // 1970-01-01 = Thursday
8469 };
8470 pandas::DatetimeArray arr(values);
8471 pandas::DatetimeMixinIndex idx(arr);
8472
8473 std::vector<std::string> names = idx.day_name();
8474
8475 bool passed = (names.size() == 1 && names[0] == "Thursday");
8476 if (!passed) {
8477 std::cout << " [FAIL] : in pd_test_datetime_mixin_day_name() got: " << names[0] << std::endl;
8478 throw std::runtime_error("pd_test_datetime_mixin_day_name failed");
8479 }
8480
8481 std::cout << " -> tests passed" << std::endl;
8482}
day_of_week (pd_test_3_all.cpp:22018)
22008void test_dt_aliases() {
22009 std::cout << "========= dt accessor aliases ====================";
22010
22011 std::vector<numpy::datetime64> dates = {
22012 numpy::datetime64("2023-01-15"),
22013 numpy::datetime64("2023-06-20")
22014 };
22015 pandas::Series<numpy::datetime64> s(dates);
22016
22017 auto dow1 = s.dt().dayofweek();
22018 auto dow2 = s.dt().day_of_week();
22019 auto dow3 = s.dt().weekday();
22020
22021 if (dow1[0] != dow2[0] || dow1[0] != dow3[0]) {
22022 throw std::runtime_error("dt aliases: dayofweek/day_of_week/weekday mismatch");
22023 }
22024
22025 auto doy1 = s.dt().dayofyear();
22026 auto doy2 = s.dt().day_of_year();
22027
22028 if (doy1[0] != doy2[0]) {
day_of_year (pd_test_3_all.cpp:22026)
22016 auto dow1 = s.dt().dayofweek();
22017 auto dow2 = s.dt().day_of_week();
22018 auto dow3 = s.dt().weekday();
22019
22020 if (dow1[0] != dow2[0] || dow1[0] != dow3[0]) {
22021 throw std::runtime_error("dt aliases: dayofweek/day_of_week/weekday mismatch");
22022 }
22023
22024 auto doy1 = s.dt().dayofyear();
22025 auto doy2 = s.dt().day_of_year();
22026
22027 if (doy1[0] != doy2[0]) {
22028 throw std::runtime_error("dt aliases: dayofyear/day_of_year mismatch");
22029 }
22030
22031 std::cout << " -> tests passed" << std::endl;
22032}
22033
22034void test_dt_days_in_month() {
22035 std::cout << "========= dt.days_in_month ======================";
dayofweek (pd_test_1_all.cpp:7565)
7555 // 1970-01-01 was a Thursday (day 3)
7556 std::vector<std::optional<numpy::datetime64>> values = {
7557 make_dt(0), // Thursday (3)
7558 make_dt(NS_PER_DAY), // Friday (4)
7559 make_dt(2 * NS_PER_DAY), // Saturday (5)
7560 make_dt(3 * NS_PER_DAY) // Sunday (6)
7561 };
7562 pandas::DatetimeArray arr(values);
7563 pandas::DatetimeIndex idx(arr);
7564
7565 auto dow = idx.dayofweek();
7566
7567 bool passed = (dow.size() == 4);
7568 if (!passed) {
7569 std::cout << " [FAIL] : in pd_test_datetime_index_dayofweek()" << std::endl;
7570 throw std::runtime_error("pd_test_datetime_index_dayofweek failed");
7571 }
7572
7573 std::cout << " -> tests passed" << std::endl;
7574}
dayofyear (pd_test_3_all.cpp:18582)
18572 auto seconds = s.dt().second();
18573 if (seconds[0] != 45 || seconds[1] != 30 || seconds[2] != 59) {
18574 std::cout << " [FAIL] : second() failed" << std::endl;
18575 throw std::runtime_error("pd_test_dt_time_components: second() failed");
18576 }
18577
18578 std::cout << " -> tests passed" << std::endl;
18579}
18580
18581// ============================================================================
18582// Test dt().dayofweek(), dt().dayofyear(), dt().quarter()
18583// ============================================================================
18584
18585void pd_test_dt_derived_properties() {
18586 std::cout << "========= Series.dt().dayofweek/dayofyear/quarter() ======";
18587
18588 // 2020-01-01 is a Wednesday (dayofweek=2), dayofyear=1, Q1
18589 // 2020-07-04 is a Saturday (dayofweek=5), dayofyear=186, Q3
18590 pandas::Series<std::string> s({"2020-01-01", "2020-07-04"});
18591
18592 auto dow = s.dt().dayofweek();
days_in_month (pd_test_1_all.cpp:2766)
2756 std::cout << " [FAIL] : day[0] should be 15" << std::endl;
2757 throw std::runtime_error("pd_test_period_array_day_components failed: day[0]");
2758 }
2759 auto d1 = days[1];
2760 if (!d1.has_value() || d1.value() != 25) {
2761 std::cout << " [FAIL] : day[1] should be 25" << std::endl;
2762 throw std::runtime_error("pd_test_period_array_day_components failed: day[1]");
2763 }
2764
2765 // Days in month
2766 auto dim = arr.days_in_month();
2767 auto dim0 = dim[0];
2768 if (!dim0.has_value() || dim0.value() != 31) {
2769 std::cout << " [FAIL] : days_in_month[0] should be 31 (March)" << std::endl;
2770 throw std::runtime_error("pd_test_period_array_day_components failed: days_in_month[0]");
2771 }
2772 auto dim1 = dim[1];
2773 if (!dim1.has_value() || dim1.value() != 31) {
2774 std::cout << " [FAIL] : days_in_month[1] should be 31 (December)" << std::endl;
2775 throw std::runtime_error("pd_test_period_array_day_components failed: days_in_month[1]");
2776 }
dst (pd_test_timestamp_scalar.cpp:772)
762 }
763
764 // utcoffset
765 numpy::timedelta64 offset = localized.utcoffset();
766 if (offset.isNaT()) {
767 pass = false;
768 fail_msg = "utcoffset should not be NaT";
769 }
770
771 // dst
772 numpy::timedelta64 dst_val = localized.dst();
773 if (dst_val.isNaT()) {
774 pass = false;
775 fail_msg = "dst should not be NaT";
776 }
777
778 if (!pass) {
779 std::cout << " [FAIL] : in np_test_timestamp_tz_methods() : " << fail_msg;
780 throw std::runtime_error("np_test_timestamp_tz_methods failed: " + fail_msg);
781 }
floor (pd_test_1_all.cpp:4942)
4932 pandas::Series<double> a({1.4, 2.5, 3.6, -1.4, -2.5});
4933
4934 auto r = a.round();
4935 bool passed = std::abs(r[0] - 1.0) < 0.001 && std::abs(r[2] - 4.0) < 0.001;
4936 if (!passed) {
4937 std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : round failed" << std::endl;
4938 throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed");
4939 }
4940
4941 auto f = a.floor();
4942 passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001;
4943 if (!passed) {
4944 std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl;
4945 throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed");
4946 }
4947
4948 auto c = a.ceil();
4949 passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001;
4950 if (!passed) {
4951 std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl;
fold (pd_test_timestamp_scalar.cpp:478)
468 std::string fail_msg;
469
470 // Naive timestamp
471 pandas::Timestamp naive(2024, 6, 15);
472 if (!naive.tz().empty()) { pass = false; fail_msg = "Naive should have empty tz"; }
473 if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; }
474
475 // UTC timestamp
476 pandas::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC");
477 if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; }
478 if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; }
479
480 // Named timezone
481 pandas::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York");
482 if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; }
483 std::string tzname = ny.tzname();
484 if (tzname != "EDT" && tzname != "EST") { pass = false; fail_msg = "Summer should be EDT or EST"; }
485
486 if (!pass) {
487 std::cout << " [FAIL] : in np_test_timestamp_timezone() : " << fail_msg;
488 throw std::runtime_error("np_test_timestamp_timezone failed: " + fail_msg);
fromisocalendar (pd_test_timestamp_scalar.cpp:153)
143 }
144
145 std::cout << " -> tests passed" << std::endl;
146 }
147
148 // ============================================================================
149 // STATIC FACTORY METHODS - Plan 11 (fromisocalendar, fromisoformat, strptime)
150 // ============================================================================
151
152 void np_test_timestamp_fromisocalendar() {
153 std::cout << "========= Timestamp::fromisocalendar() ===============";
154
155 // Test 1: Basic ISO calendar to date conversion
156 // 2024, week 1, Monday (Jan 1, 2024 was Monday of week 1)
157 pandas::Timestamp ts1 = pandas::Timestamp::fromisocalendar(2024, 1, 1);
158 if (ts1.year() != 2024 || ts1.month() != 1 || ts1.day() != 1) {
159 throw std::runtime_error("fromisocalendar failed: 2024-W01-1 should be 2024-01-01");
160 }
161
162 // Test 2: 2020, week 1, Wednesday (Jan 1, 2020 was Wednesday)
163 pandas::Timestamp ts2 = pandas::Timestamp::fromisocalendar(2020, 1, 3);
fromisoformat (pd_test_timestamp_scalar.cpp:210)
200 threw = true;
201 }
202 if (!threw) {
203 throw std::runtime_error("fromisocalendar failed: should throw for weekday 8");
204 }
205
206 std::cout << " -> tests passed" << std::endl;
207 }
208
209 void np_test_timestamp_fromisoformat() {
210 std::cout << "========= Timestamp::fromisoformat() ==================";
211
212 // Test 1: Date only
213 pandas::Timestamp ts1 = pandas::Timestamp::fromisoformat("2024-03-15");
214 if (ts1.year() != 2024 || ts1.month() != 3 || ts1.day() != 15) {
215 throw std::runtime_error("fromisoformat failed: date only parsing");
216 }
217
218 // Test 2: Date and time with T separator
219 pandas::Timestamp ts2 = pandas::Timestamp::fromisoformat("2024-03-15T14:30:00");
220 if (ts2.year() != 2024 || ts2.month() != 3 || ts2.day() != 15 ||
fromordinal (pd_test_timestamp_scalar.cpp:118)
108 }
109
110 // fromtimestamp - Unix epoch
111 pandas::Timestamp epoch = pandas::Timestamp::fromtimestamp(0.0);
112 if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) {
113 pass = false;
114 fail_msg = "fromtimestamp(0) should be epoch";
115 }
116
117 // fromordinal
118 pandas::Timestamp from_ord = pandas::Timestamp::fromordinal(738678);
119 if (from_ord.isNaT()) {
120 pass = false;
121 fail_msg = "fromordinal should not return NaT";
122 }
123
124 // combine
125 pandas::Timestamp combined = pandas::Timestamp::combine({2024, 6, 15}, {12, 30, 45, 0});
126 if (combined.year() != 2024 || combined.hour() != 12) {
127 pass = false;
128 fail_msg = "combine() values incorrect";
fromtimestamp (pd_test_timestamp_scalar.cpp:111)
101 }
102
103 // utcnow()
104 pandas::Timestamp utcnow = pandas::Timestamp::utcnow();
105 if (utcnow.isNaT() || utcnow.tz() != "UTC") {
106 pass = false;
107 fail_msg = "utcnow() should have UTC timezone";
108 }
109
110 // fromtimestamp - Unix epoch
111 pandas::Timestamp epoch = pandas::Timestamp::fromtimestamp(0.0);
112 if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) {
113 pass = false;
114 fail_msg = "fromtimestamp(0) should be epoch";
115 }
116
117 // fromordinal
118 pandas::Timestamp from_ord = pandas::Timestamp::fromordinal(738678);
119 if (from_ord.isNaT()) {
120 pass = false;
121 fail_msg = "fromordinal should not return NaT";
hour (pd_test_1_all.cpp:7476)
7466 std::cout << "========= hour property ===============================";
7467
7468 std::vector<std::optional<numpy::datetime64>> values = {
7469 make_dt(0), // Hour 0
7470 make_dt(6 * NS_PER_HOUR), // Hour 6
7471 make_dt(23 * NS_PER_HOUR) // Hour 23
7472 };
7473 pandas::DatetimeArray arr(values);
7474 pandas::DatetimeIndex idx(arr);
7475
7476 auto hours = idx.hour();
7477
7478 bool passed = (hours.size() == 3);
7479 auto h0 = hours[0];
7480 auto h1 = hours[1];
7481 auto h2 = hours[2];
7482 passed = passed && h0.has_value() && *h0 == 0;
7483 passed = passed && h1.has_value() && *h1 == 6;
7484 passed = passed && h2.has_value() && *h2 == 23;
7485
7486 if (!passed) {
isNaT (pd_test_3_all.cpp:1523)
1513 }
1514
1515 // Case B: pandas::Timedelta == pandas::Timedelta
1516 {
1517 static_assert(std::is_same_v<pandas::Timedelta, pandas::Timedelta>,
1518 "pandas::Timedelta must alias pandas::Timedelta");
1519 }
1520
1521 // Case C: pandas::NaT is a NaT-valued Timestamp
1522 {
1523 if (!pandas::NaT.isNaT()) {
1524 throw std::runtime_error("pandas::NaT is not a NaT value");
1525 }
1526 pandas::Timestamp default_ts;
1527 if (default_ts.isNaT() != pandas::NaT.isNaT()) {
1528 throw std::runtime_error(
1529 "pandas::NaT and default Timestamp NaT-state mismatch");
1530 }
1531 }
1532
1533 // Case D: round-trip - reproduces the failing test pattern
isocalendar (pd_test_3_all.cpp:22134)
22124}
22125
22126void test_dt_isocalendar() {
22127 std::cout << "========= dt.isocalendar =========================";
22128
22129 std::vector<numpy::datetime64> dates = {
22130 numpy::datetime64("2023-01-15")
22131 };
22132 pandas::Series<numpy::datetime64> s(dates);
22133
22134 auto iso = s.dt().isocalendar();
22135 if (iso.year.size() != 1 || iso.week.size() != 1 || iso.day.size() != 1) {
22136 throw std::runtime_error("dt.isocalendar: wrong size");
22137 }
22138 if (iso.year[0] != 2023) {
22139 throw std::runtime_error("dt.isocalendar: wrong year");
22140 }
22141
22142 std::cout << " -> tests passed" << std::endl;
22143}
isoformat (pd_test_timedelta_scalar.cpp:465)
455 if (nat.toString() != "NaT") {
456 std::cout << "[FAIL] np_test_timedelta_strings: toString(NaT) expected 'NaT', got '"
457 << nat.toString() << "'" << std::endl;
458 errors++;
459 }
460 }
461
462 // isoformat
463 {
464 pandas::Timedelta td(1, 2, 30);
465 std::string iso = td.isoformat();
466 if (iso.find("P1D") == std::string::npos) {
467 std::cout << "[FAIL] np_test_timedelta_strings: isoformat expected 'P1D...', got '"
468 << iso << "'" << std::endl;
469 errors++;
470 }
471 }
472
473 // components_str
474 {
475 pandas::Timedelta td(1, 2, 30, 45, 100, 200, 300);
isoweekday (pd_test_timestamp_scalar.cpp:620)
610 std::string fail_msg;
611
612 pandas::Timestamp ts(2024, 6, 15);
613
614 // isocalendar
615 auto [iso_year, iso_week, iso_day] = ts.isocalendar();
616 if (iso_year != 2024) { pass = false; fail_msg = "ISO year should be 2024"; }
617 if (iso_week < 1 || iso_week > 53) { pass = false; fail_msg = "ISO week range"; }
618 if (iso_day < 1 || iso_day > 7) { pass = false; fail_msg = "ISO day range 1-7"; }
619
620 // isoweekday (1=Monday, 7=Sunday)
621 int isowd = ts.isoweekday();
622 if (isowd != 6) { pass = false; fail_msg = "2024-06-15 is Saturday = 6"; }
623
624 // weekday (0=Monday, 6=Sunday)
625 int wd = ts.weekday();
626 if (wd != 5) { pass = false; fail_msg = "2024-06-15 is Saturday = 5"; }
627
628 if (!pass) {
629 std::cout << " [FAIL] : in np_test_timestamp_calendar() : " << fail_msg;
630 throw std::runtime_error("np_test_timestamp_calendar failed: " + fail_msg);
microsecond (pd_test_timestamp_scalar.cpp:45)
35 // Component constructor
36 pandas::Timestamp ts1(2024, 6, 15, 14, 30, 45);
37 if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
38 ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
39 pass = false;
40 fail_msg = "Component constructor values incorrect";
41 }
42
43 // With microseconds and nanoseconds
44 pandas::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
45 if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
46 pass = false;
47 fail_msg = "Microsecond/nanosecond values incorrect";
48 }
49
50 // String constructor - ISO format
51 pandas::Timestamp ts3("2024-06-15T14:30:45");
52 if (ts3.year() != 2024 || ts3.month() != 6 || ts3.day() != 15) {
53 pass = false;
54 fail_msg = "String constructor parse failed";
55 }
month (pd_test_1_all.cpp:1180)
1170 void pd_test_datetime_array_component_month_day() {
1171 std::cout << "========= DatetimeArray: month/day components ======================= ";
1172
1173 pandas::DatetimeArray arr(std::vector<std::string>{
1174 "2023-03-15",
1175 "2023-12-25",
1176 "NaT"
1177 });
1178
1179 // Month
1180 auto months = arr.month();
1181 auto m0 = months[0];
1182 if (!m0.has_value() || m0.value() != 3) {
1183 std::cout << " [FAIL] : month[0] should be 3" << std::endl;
1184 throw std::runtime_error("pd_test_datetime_array_component_month_day failed: month[0]");
1185 }
1186 auto m1 = months[1];
1187 if (!m1.has_value() || m1.value() != 12) {
1188 std::cout << " [FAIL] : month[1] should be 12" << std::endl;
1189 throw std::runtime_error("pd_test_datetime_array_component_month_day failed: month[1]");
1190 }
month_name (pd_test_1_all.cpp:8454)
8444void pd_test_datetime_mixin_month_name() {
8445 std::cout << "========= month_name ==================================";
8446
8447 std::vector<std::optional<numpy::datetime64>> values = {
8448 numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond) // 1970-01-01 = January
8449 };
8450 pandas::DatetimeArray arr(values);
8451 pandas::DatetimeMixinIndex idx(arr);
8452
8453 std::vector<std::string> names = idx.month_name();
8454
8455 bool passed = (names.size() == 1 && names[0] == "January");
8456 if (!passed) {
8457 std::cout << " [FAIL] : in pd_test_datetime_mixin_month_name() got: " << names[0] << std::endl;
8458 throw std::runtime_error("pd_test_datetime_mixin_month_name failed");
8459 }
8460
8461 std::cout << " -> tests passed" << std::endl;
8462}
nanosecond (pd_test_timestamp_scalar.cpp:45)
35 // Component constructor
36 pandas::Timestamp ts1(2024, 6, 15, 14, 30, 45);
37 if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
38 ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
39 pass = false;
40 fail_msg = "Component constructor values incorrect";
41 }
42
43 // With microseconds and nanoseconds
44 pandas::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
45 if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
46 pass = false;
47 fail_msg = "Microsecond/nanosecond values incorrect";
48 }
49
50 // String constructor - ISO format
51 pandas::Timestamp ts3("2024-06-15T14:30:45");
52 if (ts3.year() != 2024 || ts3.month() != 6 || ts3.day() != 15) {
53 pass = false;
54 fail_msg = "String constructor parse failed";
55 }
normalize (pd_test_1_all.cpp:8723)
8713void pd_test_datetime_mixin_normalize() {
8714 std::cout << "========= normalize ===================================";
8715
8716 // Create datetime with time component
8717 std::vector<std::optional<numpy::datetime64>> values = {
8718 numpy::datetime64(86400000000000LL + 3600000000000LL, numpy::DateTimeUnit::Nanosecond) // 1 day + 1 hour
8719 };
8720 pandas::DatetimeArray arr(values);
8721 pandas::DatetimeMixinIndex idx(arr);
8722
8723 pandas::DatetimeMixinIndex normalized = idx.normalize();
8724
8725 bool passed = (normalized.size() == 1);
8726 if (!passed) {
8727 std::cout << " [FAIL] : in pd_test_datetime_mixin_normalize()" << std::endl;
8728 throw std::runtime_error("pd_test_datetime_mixin_normalize failed");
8729 }
8730
8731 std::cout << " -> tests passed" << std::endl;
8732}
now (pd_test_3_all.cpp:20077)
20067 bool passed = months_default[0] == "June" && days_default[0] == "Monday";
20068 if (!passed) {
20069 std::cout << " [FAIL] : in pd_test_name_locale_params()" << std::endl;
20070 throw std::runtime_error("pd_test_name_locale_params failed");
20071 }
20072
20073 std::cout << " -> tests passed" << std::endl;
20074}
20075
20076// ============================================================================
20077// Test Period.now() with tz parameter
20078// ============================================================================
20079
20080void pd_test_period_now_tz() {
20081 std::cout << "========= Period.now(tz) ================================";
20082
20083 // Test now() with default (local time)
20084 auto p_local = pandas::Period::now("D");
20085
20086 // Test now() with UTC timezone
20087 auto p_utc = pandas::Period::now("D", "UTC");
quarter (pd_test_1_all.cpp:1218)
1208 void pd_test_datetime_array_quarter() {
1209 std::cout << "========= DatetimeArray: quarter ======================= ";
1210
1211 pandas::DatetimeArray arr(std::vector<std::string>{
1212 "2023-01-15", // Q1
1213 "2023-05-20", // Q2
1214 "2023-09-10", // Q3
1215 "2023-11-25" // Q4
1216 });
1217
1218 auto quarters = arr.quarter();
1219
1220 auto q0 = quarters[0];
1221 if (!q0.has_value() || q0.value() != 1) {
1222 std::cout << " [FAIL] : quarter[0] should be 1" << std::endl;
1223 throw std::runtime_error("pd_test_datetime_array_quarter failed: quarter[0]");
1224 }
1225 auto q1 = quarters[1];
1226 if (!q1.has_value() || q1.value() != 2) {
1227 std::cout << " [FAIL] : quarter[1] should be 2" << std::endl;
1228 throw std::runtime_error("pd_test_datetime_array_quarter failed: quarter[1]");
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
result (pd_test_1_all.cpp:15406)
15396 data.setElementAt({0}, numpy::datetime64(100LL, numpy::DateTimeUnit::Nanosecond));
15397 data.setElementAt({1}, numpy::datetime64(200LL, numpy::DateTimeUnit::Nanosecond));
15398
15399 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
15400 mask.setElementAt({0}, numpy::bool_(false));
15401 mask.setElementAt({1}, numpy::bool_(false));
15402
15403 pandas::DatetimeArray arr(data, mask);
15404 pandas::DatetimeIndexBase idx(arr, "original");
15405
15406 // Create join result (int64 values)
15407 numpy::NDArray<numpy::int64> join_result(std::vector<size_t>{3});
15408 join_result.setElementAt({0}, numpy::int64(500LL));
15409 join_result.setElementAt({1}, numpy::int64(600LL));
15410 join_result.setElementAt({2}, numpy::int64(700LL));
15411
15412 auto new_idx = idx._from_join_target(join_result);
15413
15414 bool passed = (new_idx.size() == 3 &&
15415 new_idx.name().has_value() && *new_idx.name() == "original");
15416 if (!passed) {
round (pd_test_1_all.cpp:1688)
1678 void pd_test_floating_array_rounding() {
1679 std::cout << "========= FloatingArray: rounding ======================= ";
1680
1681 pandas::FloatingArray<double> arr({
1682 std::optional<double>(1.234),
1683 std::optional<double>(2.567),
1684 std::nullopt
1685 });
1686
1687 auto rounded = arr.round(2);
1688 if (std::abs(rounded[0].value() - 1.23) > 0.001 ||
1689 std::abs(rounded[1].value() - 2.57) > 0.001) {
1690 std::cout << " [FAIL] : in pd_test_floating_array_rounding() : round(2)" << std::endl;
1691 throw std::runtime_error("pd_test_floating_array_rounding failed: round(2)");
1692 }
1693
1694 if (!rounded.is_na(2)) {
1695 std::cout << " [FAIL] : in pd_test_floating_array_rounding() : round should preserve NA" << std::endl;
1696 throw std::runtime_error("pd_test_floating_array_rounding failed: NA preservation");
1697 }
second (pd_test_1_all.cpp:7534)
7524 std::cout << "========= second property =============================";
7525
7526 std::vector<std::optional<numpy::datetime64>> values = {
7527 make_dt(0), // Second 0
7528 make_dt(30 * NS_PER_SEC), // Second 30
7529 make_dt(59 * NS_PER_SEC) // Second 59
7530 };
7531 pandas::DatetimeArray arr(values);
7532 pandas::DatetimeIndex idx(arr);
7533
7534 auto seconds = idx.second();
7535
7536 bool passed = (seconds.size() == 3);
7537 auto s0 = seconds[0];
7538 auto s1 = seconds[1];
7539 auto s2 = seconds[2];
7540 passed = passed && s0.has_value() && *s0 == 0;
7541 passed = passed && s1.has_value() && *s1 == 30;
7542 passed = passed && s2.has_value() && *s2 == 59;
7543
7544 if (!passed) {
setTimezone (pd_test_3_all.cpp:25427)
25417void pd_test_dst_offset_spring_forward() {
25418 std::cout << "========= apply_offset_dst_aware: spring forward =======";
25419 auto tz = numpy::getTimezone("US/Eastern");
25420 if (!tz) {
25421 std::cout << " -> skipped (timezone not available)" << std::endl;
25422 return;
25423 }
25424 // March 11, 2023 12:00 EST = 17:00 UTC
25425 int64_t utc_ns = pandas::Timestamp::componentsToNanos(2023, 3, 11, 17, 0, 0, 0, 0);
25426 pandas::Timestamp ts(utc_ns, "");
25427 ts.setTimezone(tz);
25428 pandas::DateOffset off(1, false, 0, 0, 0, 1); // +1 day
25429 auto result = pandas::datetime_utils::apply_offset_dst_aware(off, ts);
25430 if (!result.timezone())
25431 throw std::runtime_error("apply_offset DST: timezone lost");
25432 std::cout << " -> tests passed" << std::endl;
25433}
25434
25435void pd_test_dst_offset_naive_stays_naive() {
25436 std::cout << "========= apply_offset_dst_aware: naive stays naive ====";
25437 int64_t ns = pandas::Timestamp::componentsToNanos(2023, 1, 1, 0, 0, 0, 0, 0);
ss (pd_test_3_all.cpp:27670)
27660 fail++;
27661 } else {
27662 auto cats = str_s->get_cat_categories();
27663 if (cats.size() != 3) {
27664 std::cout << " FAIL: expected 3 categories, got " << cats.size() << std::endl;
27665 fail++;
27666 }
27667 }
27668 }
27669
27670 pandas::Series<std::string> ss({"a", "b", "a", "c"}, "strs");
27671 auto result2 = ss.astype("category");
27672 auto* str_s2 = dynamic_cast<pandas::Series<std::string>*>(result2.get());
27673 if (!str_s2) {
27674 std::cout << " FAIL: expected Series<string> for string->category" << std::endl;
27675 fail++;
27676 } else {
27677 if (str_s2->dtype_name() != "category") {
27678 std::cout << " FAIL: dtype should be category" << std::endl;
27679 fail++;
27680 }
strftime (pd_test_1_all.cpp:8434)
8424void pd_test_datetime_mixin_strftime() {
8425 std::cout << "========= strftime ====================================";
8426
8427 std::vector<std::optional<numpy::datetime64>> values = {
8428 numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond), // 1970-01-01
8429 numpy::datetime64(86400000000000LL, numpy::DateTimeUnit::Nanosecond) // 1970-01-02
8430 };
8431 pandas::DatetimeArray arr(values);
8432 pandas::DatetimeMixinIndex idx(arr);
8433
8434 std::vector<std::string> formatted = idx.strftime("%Y-%m-%d");
8435
8436 bool passed = (formatted.size() == 2 && !formatted[0].empty() && !formatted[1].empty());
8437 if (!passed) {
8438 std::cout << " [FAIL] : in pd_test_datetime_mixin_strftime()" << std::endl;
8439 throw std::runtime_error("pd_test_datetime_mixin_strftime failed");
8440 }
8441
8442 std::cout << " -> tests passed" << std::endl;
8443}
strptime (pd_test_timestamp_scalar.cpp:280)
270 threw = true;
271 }
272 if (!threw) {
273 throw std::runtime_error("fromisoformat failed: should throw for too short string");
274 }
275
276 std::cout << " -> tests passed" << std::endl;
277 }
278
279 void np_test_timestamp_strptime() {
280 std::cout << "========= Timestamp::strptime() =======================";
281
282 // Test 1: Basic date parsing
283 pandas::Timestamp ts1 = pandas::Timestamp::strptime("2024-03-15", "%Y-%m-%d");
284 if (ts1.year() != 2024 || ts1.month() != 3 || ts1.day() != 15) {
285 throw std::runtime_error("strptime failed: basic date parsing");
286 }
287
288 // Test 2: Date and time parsing
289 pandas::Timestamp ts2 = pandas::Timestamp::strptime("2024-03-15 14:30:45", "%Y-%m-%d %H:%M:%S");
290 if (ts2.year() != 2024 || ts2.month() != 3 || ts2.day() != 15 ||
time (pd_test_timestamp_scalar.cpp:535)
525 if (posix <= 0) { pass = false; fail_msg = "POSIX timestamp should be positive"; }
526
527 // timetuple
528 auto [y, mo, d, h, mi, s] = ts.timetuple();
529 if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; }
530
531 // date/time tuples
532 auto [dy, dm, dd] = ts.date();
533 if (dy != 2024) { pass = false; fail_msg = "date tuple year"; }
534
535 auto [th, tmi, ts2, tus] = ts.time();
536 if (th != 12) { pass = false; fail_msg = "time tuple hour"; }
537
538 // Julian date
539 double jd = ts.to_julian_date();
540 if (jd < 2400000) { pass = false; fail_msg = "Julian date should be reasonable"; }
541
542 // Ordinal
543 int ord = ts.toordinal();
544 if (ord <= 0) { pass = false; fail_msg = "Ordinal should be positive"; }
timestamp (pd_test_2_all.cpp:16572)
16562 pandas::DataFrame df(data);
16563 df.set_index(std::make_unique<pandas::PeriodIndex>(period_idx));
16564
16565 // Verify it's a PeriodIndex
16566 const pandas::PeriodIndex* pidx = dynamic_cast<const pandas::PeriodIndex*>(&df.index());
16567 if (!pidx) {
16568 std::cout << " [FAIL] : in pd_test_to_timestamp_basic() : index is not PeriodIndex" << std::endl;
16569 throw std::runtime_error("pd_test_to_timestamp_basic failed: index is not PeriodIndex");
16570 }
16571
16572 // Convert to timestamp (start of period - default)
16573 pandas::DataFrame df_start = df.to_timestamp();
16574
16575 // Verify it's now a DatetimeIndex
16576 const pandas::DatetimeIndex* dtidx = dynamic_cast<const pandas::DatetimeIndex*>(&df_start.index());
16577 if (!dtidx) {
16578 std::cout << " [FAIL] : in pd_test_to_timestamp_basic() : result index is not DatetimeIndex" << std::endl;
16579 throw std::runtime_error("pd_test_to_timestamp_basic failed: result index is not DatetimeIndex");
16580 }
16581
16582 // Verify data is preserved
timetuple (pd_test_timestamp_scalar.cpp:528)
518 // to_pydatetime
519 std::tm tm = ts.to_pydatetime();
520 if (tm.tm_year != 124) { pass = false; fail_msg = "tm_year should be 124 (2024-1900)"; }
521 if (tm.tm_mon != 5) { pass = false; fail_msg = "tm_mon should be 5 (June)"; }
522
523 // timestamp
524 double posix = ts.timestamp();
525 if (posix <= 0) { pass = false; fail_msg = "POSIX timestamp should be positive"; }
526
527 // timetuple
528 auto [y, mo, d, h, mi, s] = ts.timetuple();
529 if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; }
530
531 // date/time tuples
532 auto [dy, dm, dd] = ts.date();
533 if (dy != 2024) { pass = false; fail_msg = "date tuple year"; }
534
535 auto [th, tmi, ts2, tus] = ts.time();
536 if (th != 12) { pass = false; fail_msg = "time tuple hour"; }
537
538 // Julian date
timetz (pd_test_timestamp_scalar.cpp:1042)
1032 // Test 3: utctimetuple() - returns (year, month, day, hour, minute, second) in UTC
1033 pandas::Timestamp ts_utc(2024, 6, 15, 14, 30, 45, 0, 0, "UTC");
1034 auto utc_tuple = ts_utc.utctimetuple();
1035 if (pass && std::get<0>(utc_tuple) != 2024) { pass = false; fail_msg = "utctimetuple year mismatch"; }
1036 if (pass && std::get<1>(utc_tuple) != 6) { pass = false; fail_msg = "utctimetuple month mismatch"; }
1037 if (pass && std::get<2>(utc_tuple) != 15) { pass = false; fail_msg = "utctimetuple day mismatch"; }
1038 if (pass && std::get<3>(utc_tuple) != 14) { pass = false; fail_msg = "utctimetuple hour mismatch"; }
1039 if (pass && std::get<4>(utc_tuple) != 30) { pass = false; fail_msg = "utctimetuple minute mismatch"; }
1040 if (pass && std::get<5>(utc_tuple) != 45) { pass = false; fail_msg = "utctimetuple second mismatch"; }
1041
1042 // Test 4: timetz() - returns (hour, minute, second, microsecond, tz_offset_seconds)
1043 pandas::Timestamp ts_tz(2024, 6, 15, 14, 30, 45, 123456, 0, "UTC");
1044 auto time_tuple = ts_tz.timetz();
1045 if (pass && std::get<0>(time_tuple) != 14) { pass = false; fail_msg = "timetz hour mismatch"; }
1046 if (pass && std::get<1>(time_tuple) != 30) { pass = false; fail_msg = "timetz minute mismatch"; }
1047 if (pass && std::get<2>(time_tuple) != 45) { pass = false; fail_msg = "timetz second mismatch"; }
1048 if (pass && std::get<3>(time_tuple) != 123456) { pass = false; fail_msg = "timetz microsecond mismatch"; }
1049 // UTC offset should be 0 for UTC timezone
1050 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)); }
1051
1052 if (!pass) {
timezone (pd_test_2_all.cpp:17898)
17888 // Use UTC timestamps and localize to a timezone first
17889 std::vector<std::optional<numpy::datetime64>> datetimes;
17890 // 2018-09-15 05:30:00 UTC = 1537076200 seconds since epoch
17891 datetimes.push_back(numpy::datetime64(1537076200000000000LL, numpy::DateTimeUnit::Nanosecond));
17892 // 2018-09-16 05:30:00 UTC
17893 datetimes.push_back(numpy::datetime64(1537162600000000000LL, numpy::DateTimeUnit::Nanosecond));
17894
17895 pandas::DatetimeArray dt_arr(datetimes);
17896 pandas::DatetimeIndex dt_idx(dt_arr, "timestamp");
17897
17898 // Localize to US/Eastern timezone (timezone-aware)
17899 pandas::DatetimeIndex tz_aware_idx = dt_idx.tz_localize("US/Eastern");
17900
17901 // Create DataFrame with timezone-aware DatetimeIndex
17902 std::map<std::string, std::vector<double>> data;
17903 data["value"] = {1.0, 2.0};
17904 pandas::DataFrame df(data);
17905 df.set_index(std::make_unique<pandas::DatetimeIndex>(tz_aware_idx));
17906
17907 // Verify the index is timezone-aware
17908 const pandas::DatetimeIndex* original_idx = dynamic_cast<const pandas::DatetimeIndex*>(&df.index());
toString (pd_test_1_all.cpp:9539)
9529void pd_test_timedelta_rounding_params() {
9530 std::cout << "========= Timedelta rounding with DST params =====";
9531
9532 // Create a Timedelta: 1h 30m 45s
9533 // Constructor is: (days, hours, minutes, seconds, ...)
9534 pandas::Timedelta td(0, 1, 30, 45); // 0 days, 1h, 30m, 45s
9535
9536 // Test floor with ambiguous/nonexistent params
9537 pandas::Timedelta floored = td.floor("h", "raise", "raise");
9538 std::cout << std::endl << " floor('h'): " << floored.toString();
9539
9540 // Test ceil with ambiguous/nonexistent params
9541 pandas::Timedelta ceiled = td.ceil("h", "raise", "raise");
9542 std::cout << std::endl << " ceil('h'): " << ceiled.toString();
9543
9544 // Test round with ambiguous/nonexistent params
9545 pandas::Timedelta rounded = td.round("h", "raise", "raise");
9546 std::cout << std::endl << " round('h'): " << rounded.toString();
9547
9548 // Verify results:
today (pd_test_5_all.cpp:108359)
108349 auto spec = get_fill_spec(row.fill_kind);
108350
108351 // patch 3 (Int64/boolean/string nullable-extension): route through the
108352 // nullable runner so dtype_override_ is set BEFORE reindex_with_spec.
108353 if (row.storage == "Int64")
108354 return run_nullable_int64({10, 20, 30}, new_idx, spec);
108355 if (row.storage == "boolean")
108356 return run_nullable_bool({true, false, true}, new_idx, spec);
108357 if (row.storage == "string_ea")
108358 return run_nullable_string({"x", "y", "z"}, new_idx, spec);
108359 // patch 4 (Series<numpy::float16>): no instantiation today (see plan body
108360 // for the extern-template prescription). Signal a SKIP up the chain so
108361 // the row is counted as deferred, not failed. The marker uses the same
108362 // <EXC>:F16_NOT_INSTANTIATED contract that check_row's SKIP branch
108363 // recognises.
108364 if (row.storage == "float16")
108365 throw std::runtime_error("F16_NOT_INSTANTIATED: see plan patch 4");
108366
108367 // Phase-3B nullable-extension storages — no PandasCore constructor today
108368 // (add_column_nullable<T> only specialises for int64_t/bool/std::string at
108369 // pd_dataframe.h:5946-5947). When Phase-3B lands, replace these throws
toordinal (pd_test_timestamp_scalar.cpp:543)
533 if (dy != 2024) { pass = false; fail_msg = "date tuple year"; }
534
535 auto [th, tmi, ts2, tus] = ts.time();
536 if (th != 12) { pass = false; fail_msg = "time tuple hour"; }
537
538 // Julian date
539 double jd = ts.to_julian_date();
540 if (jd < 2400000) { pass = false; fail_msg = "Julian date should be reasonable"; }
541
542 // Ordinal
543 int ord = ts.toordinal();
544 if (ord <= 0) { pass = false; fail_msg = "Ordinal should be positive"; }
545
546 if (!pass) {
547 std::cout << " [FAIL] : in np_test_timestamp_conversions() : " << fail_msg;
548 throw std::runtime_error("np_test_timestamp_conversions failed: " + fail_msg);
549 }
550
551 std::cout << " -> tests passed" << std::endl;
552 }
tz (pd_test_2_all.cpp:17914)
17904 pandas::DataFrame df(data);
17905 df.set_index(std::make_unique<pandas::DatetimeIndex>(tz_aware_idx));
17906
17907 // Verify the index is timezone-aware
17908 const pandas::DatetimeIndex* original_idx = dynamic_cast<const pandas::DatetimeIndex*>(&df.index());
17909 if (!original_idx) {
17910 std::cout << " [FAIL] : in pd_test_tz_convert_basic() : index is not DatetimeIndex" << std::endl;
17911 throw std::runtime_error("pd_test_tz_convert_basic failed: index is not DatetimeIndex");
17912 }
17913
17914 std::string original_tz = original_idx->tz();
17915 if (original_tz.empty()) {
17916 std::cout << " [FAIL] : in pd_test_tz_convert_basic() : original index is not timezone-aware" << std::endl;
17917 throw std::runtime_error("pd_test_tz_convert_basic failed: original index is not timezone-aware");
17918 }
17919
17920 // Convert to Asia/Shanghai timezone
17921 pandas::DataFrame df_shanghai = df.tz_convert("Asia/Shanghai");
17922
17923 // Verify result has a DatetimeIndex
17924 const pandas::DatetimeIndex* converted_idx = dynamic_cast<const pandas::DatetimeIndex*>(&df_shanghai.index());
tzinfo (pd_test_timestamp_scalar.cpp:473)
463 void np_test_timestamp_timezone() {
464 std::cout << "========= timestamp: timezone properties =========================";
465
466 auto pass = true;
467 std::string fail_msg;
468
469 // Naive timestamp
470 pandas::Timestamp naive(2024, 6, 15);
471 if (!naive.tz().empty()) { pass = false; fail_msg = "Naive should have empty tz"; }
472 if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; }
473
474 // UTC timestamp
475 pandas::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC");
476 if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; }
477 if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; }
478
479 // Named timezone
480 pandas::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York");
481 if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; }
482 std::string tzname = ny.tzname();
tzname (pd_test_timestamp_scalar.cpp:483)
473 if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; }
474
475 // UTC timestamp
476 pandas::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC");
477 if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; }
478 if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; }
479
480 // Named timezone
481 pandas::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York");
482 if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; }
483 std::string tzname = ny.tzname();
484 if (tzname != "EDT" && tzname != "EST") { pass = false; fail_msg = "Summer should be EDT or EST"; }
485
486 if (!pass) {
487 std::cout << " [FAIL] : in np_test_timestamp_timezone() : " << fail_msg;
488 throw std::runtime_error("np_test_timestamp_timezone failed: " + fail_msg);
489 }
490
491 std::cout << " -> tests passed" << std::endl;
492 }
utcfromtimestamp (pd_test_timestamp_scalar.cpp:1020)
1010 }
1011 if (pass && ts_from_nanos.month() != 6) {
1012 pass = false;
1013 fail_msg = "Timestamp(int64_t) month should be 6, got " + std::to_string(ts_from_nanos.month());
1014 }
1015 if (pass && ts_from_nanos.day() != 15) {
1016 pass = false;
1017 fail_msg = "Timestamp(int64_t) day should be 15, got " + std::to_string(ts_from_nanos.day());
1018 }
1019
1020 // Test 2: utcfromtimestamp(double ts) - creates UTC timestamp from POSIX timestamp
1021 // 1718454645.0 = 2024-06-15 12:30:45 UTC (verified with Python)
1022 double posix_ts = 1718454645.0;
1023 pandas::Timestamp utc_ts = pandas::Timestamp::utcfromtimestamp(posix_ts);
1024 if (pass && utc_ts.year() != 2024) { pass = false; fail_msg = "utcfromtimestamp year mismatch, got " + std::to_string(utc_ts.year()); }
1025 if (pass && utc_ts.month() != 6) { pass = false; fail_msg = "utcfromtimestamp month mismatch, got " + std::to_string(utc_ts.month()); }
1026 if (pass && utc_ts.day() != 15) { pass = false; fail_msg = "utcfromtimestamp day mismatch, got " + std::to_string(utc_ts.day()); }
1027 if (pass && utc_ts.hour() != 12) { pass = false; fail_msg = "utcfromtimestamp hour mismatch, got " + std::to_string(utc_ts.hour()); }
1028 if (pass && utc_ts.minute() != 30) { pass = false; fail_msg = "utcfromtimestamp minute mismatch, got " + std::to_string(utc_ts.minute()); }
1029 if (pass && utc_ts.second() != 45) { pass = false; fail_msg = "utcfromtimestamp second mismatch, got " + std::to_string(utc_ts.second()); }
1030 if (pass && utc_ts.tz() != "UTC") { pass = false; fail_msg = "utcfromtimestamp should have UTC timezone, got '" + utc_ts.tz() + "'"; }
utcnow (pd_test_timestamp_scalar.cpp:103)
93 fail_msg = "now() should not return NaT";
94 }
95
96 // today()
97 pandas::Timestamp today = pandas::Timestamp::today();
98 if (today.hour() != 0 || today.minute() != 0 || today.second() != 0) {
99 pass = false;
100 fail_msg = "today() should be at midnight";
101 }
102
103 // utcnow()
104 pandas::Timestamp utcnow = pandas::Timestamp::utcnow();
105 if (utcnow.isNaT() || utcnow.tz() != "UTC") {
106 pass = false;
107 fail_msg = "utcnow() should have UTC timezone";
108 }
109
110 // fromtimestamp - Unix epoch
111 pandas::Timestamp epoch = pandas::Timestamp::fromtimestamp(0.0);
112 if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) {
113 pass = false;
utcoffset (pd_test_timestamp_scalar.cpp:765)
755 }
756
757 // astimezone (alias)
758 pandas::Timestamp ast = localized.astimezone("UTC");
759 if (ast.tz() != "UTC") {
760 pass = false;
761 fail_msg = "astimezone should convert to UTC";
762 }
763
764 // utcoffset
765 numpy::timedelta64 offset = localized.utcoffset();
766 if (offset.isNaT()) {
767 pass = false;
768 fail_msg = "utcoffset should not be NaT";
769 }
770
771 // dst
772 numpy::timedelta64 dst_val = localized.dst();
773 if (dst_val.isNaT()) {
774 pass = false;
775 fail_msg = "dst should not be NaT";
utctimetuple (pd_test_timestamp_scalar.cpp:1032)
1022 double posix_ts = 1718454645.0;
1023 pandas::Timestamp utc_ts = pandas::Timestamp::utcfromtimestamp(posix_ts);
1024 if (pass && utc_ts.year() != 2024) { pass = false; fail_msg = "utcfromtimestamp year mismatch, got " + std::to_string(utc_ts.year()); }
1025 if (pass && utc_ts.month() != 6) { pass = false; fail_msg = "utcfromtimestamp month mismatch, got " + std::to_string(utc_ts.month()); }
1026 if (pass && utc_ts.day() != 15) { pass = false; fail_msg = "utcfromtimestamp day mismatch, got " + std::to_string(utc_ts.day()); }
1027 if (pass && utc_ts.hour() != 12) { pass = false; fail_msg = "utcfromtimestamp hour mismatch, got " + std::to_string(utc_ts.hour()); }
1028 if (pass && utc_ts.minute() != 30) { pass = false; fail_msg = "utcfromtimestamp minute mismatch, got " + std::to_string(utc_ts.minute()); }
1029 if (pass && utc_ts.second() != 45) { pass = false; fail_msg = "utcfromtimestamp second mismatch, got " + std::to_string(utc_ts.second()); }
1030 if (pass && utc_ts.tz() != "UTC") { pass = false; fail_msg = "utcfromtimestamp should have UTC timezone, got '" + utc_ts.tz() + "'"; }
1031
1032 // Test 3: utctimetuple() - returns (year, month, day, hour, minute, second) in UTC
1033 pandas::Timestamp ts_utc(2024, 6, 15, 14, 30, 45, 0, 0, "UTC");
1034 auto utc_tuple = ts_utc.utctimetuple();
1035 if (pass && std::get<0>(utc_tuple) != 2024) { pass = false; fail_msg = "utctimetuple year mismatch"; }
1036 if (pass && std::get<1>(utc_tuple) != 6) { pass = false; fail_msg = "utctimetuple month mismatch"; }
1037 if (pass && std::get<2>(utc_tuple) != 15) { pass = false; fail_msg = "utctimetuple day mismatch"; }
1038 if (pass && std::get<3>(utc_tuple) != 14) { pass = false; fail_msg = "utctimetuple hour mismatch"; }
1039 if (pass && std::get<4>(utc_tuple) != 30) { pass = false; fail_msg = "utctimetuple minute mismatch"; }
1040 if (pass && std::get<5>(utc_tuple) != 45) { pass = false; fail_msg = "utctimetuple second mismatch"; }
1041
1042 // Test 4: timetz() - returns (hour, minute, second, microsecond, tz_offset_seconds)
value (pd_test_1_all.cpp:88)
78 // T & T = T, T & F = F, T & NA = NA
79 // F & T = F, F & F = F, F & NA = F (False dominates)
80 // NA & T = NA, NA & F = F, NA & NA = NA
81
82 pandas::BooleanArray t({std::optional<bool>(true)});
83 pandas::BooleanArray f({std::optional<bool>(false)});
84 pandas::BooleanArray na({std::nullopt});
85
86 // T & T = T
87 auto tt = (t & t);
88 if (!tt[0].has_value() || !tt[0].value()) {
89 std::cout << " [FAIL] : in pd_test_boolean_array_kleene_and() : T & T should be T" << std::endl;
90 throw std::runtime_error("pd_test_boolean_array_kleene_and failed: T & T");
91 }
92
93 // T & F = F
94 auto tf = (t & f);
95 if (!tf[0].has_value() || tf[0].value()) {
96 std::cout << " [FAIL] : in pd_test_boolean_array_kleene_and() : T & F should be F" << std::endl;
97 throw std::runtime_error("pd_test_boolean_array_kleene_and failed: T & F");
98 }
week (pd_test_timestamp_scalar.cpp:406)
396 // 2024-06-15 is a Saturday
397 pandas::Timestamp ts(2024, 6, 15);
398
399 if (ts.dayofweek() != 5) { pass = false; fail_msg = "2024-06-15 should be Saturday (5)"; }
400 if (ts.day_of_week() != 5) { pass = false; fail_msg = "day_of_week alias"; }
401 if (ts.dayofyear() != 167) { pass = false; fail_msg = "2024-06-15 should be day 167"; }
402 if (ts.day_of_year() != 167) { pass = false; fail_msg = "day_of_year alias"; }
403 if (ts.quarter() != 2) { pass = false; fail_msg = "June is Q2"; }
404 if (ts.days_in_month() != 30) { pass = false; fail_msg = "June has 30 days"; }
405
406 int week = ts.week();
407 if (week < 1 || week > 53) { pass = false; fail_msg = "week should be 1-53"; }
408
409 if (!pass) {
410 std::cout << " [FAIL] : in np_test_timestamp_derived() : " << fail_msg;
411 throw std::runtime_error("np_test_timestamp_derived failed: " + fail_msg);
412 }
413
414 std::cout << " -> tests passed" << std::endl;
415 }
weekday (pd_test_3_all.cpp:1471)
1461 std::cout << " [FAIL] date_range 10-arg form: expected size 10, got "
1462 << idx.size() << std::endl;
1463 throw std::runtime_error("date_range 10-arg form regressed");
1464 }
1465 }
1466
1467 std::cout << " -> tests passed" << std::endl;
1468}
1469
1470void pd_test_3_all_period_weekday() {
1471 std::cout << "========= PeriodArray.weekday() ======================";
1472
1473 // Create a PeriodArray with some dates
1474 std::vector<std::optional<numpy::int64>> ordinals = {0, 1, 2, 3, 4}; // Days from epoch
1475 pandas::PeriodArray arr(ordinals, "D");
1476
1477 pandas::IntegerArray<numpy::int32> weekdays = arr.weekday();
1478
1479 if (weekdays.size() != 5) {
1480 std::cout << " [FAIL] : in pd_test_3_all_period_weekday() : size should be 5" << std::endl;
1481 throw std::runtime_error("pd_test_3_all_period_weekday failed: size");
year (pd_test_1_all.cpp:1147)
1137 void pd_test_datetime_array_component_year() {
1138 std::cout << "========= DatetimeArray: year component ======================= ";
1139
1140 pandas::DatetimeArray arr(std::vector<std::string>{
1141 "2020-01-15",
1142 "NaT",
1143 "2025-06-20"
1144 });
1145
1146 auto years = arr.year();
1147
1148 auto y0 = years[0];
1149 if (!y0.has_value() || y0.value() != 2020) {
1150 std::cout << " [FAIL] : year[0] should be 2020" << std::endl;
1151 throw std::runtime_error("pd_test_datetime_array_component_year failed: year[0]");
1152 }
1153
1154 auto y1 = years[1];
1155 if (y1.has_value()) {
1156 std::cout << " [FAIL] : year[1] should be NA (NaT)" << std::endl;