DatetimeProperties#
-
class pandas::DatetimeProperties#
pandas C++ class.
Example#
#include <pandas/pandas.h>
using namespace pandas;
// Use DatetimeProperties
DatetimeProperties obj;
// ... operations ...
Indexing / Selection#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
static int64_t |
pd_datetime_accessor.h:720 |
Statistics#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
std::vector<int64_t> |
pd_datetime_accessor.h:114 |
Time Series#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
PeriodArray |
pd_datetime_accessor.h:625 |
|
|
std::vector<numpy::datetime64> |
pd_datetime_accessor.h:641 |
|
|
std::vector<numpy::datetime64> |
pd_datetime_accessor.h:667 |
I/O#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
std::vector<numpy::datetime64> |
pd_datetime_accessor.h:700 |
Type Checking#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
std::vector<bool> |
pd_datetime_accessor.h:305 |
|
|
std::vector<bool> |
pd_datetime_accessor.h:223 |
|
|
std::vector<bool> |
pd_datetime_accessor.h:208 |
|
|
std::vector<bool> |
pd_datetime_accessor.h:257 |
|
|
std::vector<bool> |
pd_datetime_accessor.h:241 |
|
|
std::vector<bool> |
pd_datetime_accessor.h:290 |
|
|
std::vector<bool> |
pd_datetime_accessor.h:275 |
Other Methods#
Signature |
Return Type |
Location |
Example |
|---|---|---|---|
|
std::vector<numpy::datetime64> |
pd_datetime_accessor.h:690 |
|
|
std::vector<numpy::datetime64> |
pd_datetime_accessor.h:608 |
|
|
static numpy::datetime64 |
pd_datetime_accessor.h:753 |
|
|
std::vector<std::string> |
pd_datetime_accessor.h:339 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:84 |
|
|
std::vector<std::string> |
pd_datetime_accessor.h:430 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:144 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:160 |
|
|
static int |
pd_datetime_accessor.h:710 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:359 |
|
|
DatetimeArray |
pd_datetime_accessor.h:654 |
|
|
DatetimeArray |
pd_datetime_accessor.h:677 |
|
|
std::vector<numpy::datetime64> |
pd_datetime_accessor.h:591 |
|
|
static numpy::datetime64 |
pd_datetime_accessor.h:744 |
|
|
std::string |
pd_datetime_accessor.h:410 |
|
|
bool |
pd_datetime_accessor.h:37 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:99 |
|
|
IsoCalendar |
pd_datetime_accessor.h:496 |
|
|
DataFrame |
pd_datetime_accessor.h:494 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:376 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:69 |
|
|
std::vector<std::string> |
pd_datetime_accessor.h:448 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:393 |
|
|
std::vector<numpy::datetime64> |
pd_datetime_accessor.h:466 |
|
|
const ParentType& |
pd_datetime_accessor.h:35 |
|
|
explicit DatetimeProperties(const ParentType& parent) : |
pd_datetime_accessor.h:31 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:175 |
|
|
std::vector<numpy::datetime64> |
pd_datetime_accessor.h:574 |
|
|
static numpy::datetime64 |
pd_datetime_accessor.h:764 |
|
|
pandas::Series<T> |
pd_datetime_accessor.h:46 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:129 |
|
|
void |
pd_datetime_accessor.h:33 |
|
|
std::vector<std::string> |
pd_datetime_accessor.h:322 |
|
|
std::vector<std::string> |
pd_datetime_accessor.h:343 |
|
|
std::vector<std::string> |
pd_datetime_accessor.h:422 |
|
|
std::string |
pd_datetime_accessor.h:414 |
|
|
std::string |
pd_datetime_accessor.h:418 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:191 |
|
|
pandas::Series<T> |
pd_datetime_accessor.h:45 |
|
|
std::vector<int64_t> |
pd_datetime_accessor.h:54 |
Code Examples#
The following examples are extracted from the test suite.
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) {
to_period (pd_test_2_all.cpp:14554)
14544 std::cout << "====================================== [OK] pd_test_to_parquet test suite ========================" << std::endl;
14545 return 0;
14546 }
14547
14548} // namespace dataframe_tests
14549// ------------------- pd_test_to_parquet.cpp (end) -----------------------------
14550
14551// ------------------- pd_test_to_period.cpp (start) -----------------------------
14552// dataframe_tests/pd_test_to_period.cpp
14553// Test suite for DataFrame.to_period() method
14554
14555#include <iostream>
14556#include <stdexcept>
14557#include <vector>
14558#include <string>
14559#include <map>
14560
14561#include "../pandas/pd_dataframe.h"
14562
14563// CRITICAL: No using namespace directives
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_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
as_unit (pd_test_1_all.cpp:9361)
9351 data.setElementAt({1}, numpy::datetime64(2000000000LL, numpy::DateTimeUnit::Nanosecond)); // 2 seconds in ns
9352
9353 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
9354 mask.setElementAt({0}, numpy::bool_(false));
9355 mask.setElementAt({1}, numpy::bool_(false));
9356
9357 pandas::DatetimeArray arr(data, mask);
9358 pandas::DatetimeTDMixin idx(arr, "test");
9359
9360 // Convert to microseconds
9361 pandas::DatetimeTDMixin us_idx = idx.as_unit("us");
9362
9363 // Convert to same unit (should return identical)
9364 pandas::DatetimeTDMixin same_idx = idx.as_unit("ns");
9365
9366 bool passed = (us_idx.size() == 2 && same_idx.size() == 2 &&
9367 us_idx.name().has_value() && *us_idx.name() == "test");
9368 if (!passed) {
9369 std::cout << " [FAIL] : in pd_test_datetime_as_unit() : as_unit check failed" << std::endl;
9370 throw std::runtime_error("pd_test_datetime_as_unit failed");
9371 }
ceil (pd_test_1_all.cpp:4949)
4939 throw std::runtime_error("pd_test_arithmetic_series_round failed: round failed");
4940 }
4941
4942 auto f = a.floor();
4943 passed = std::abs(f[0] - 1.0) < 0.001 && std::abs(f[2] - 3.0) < 0.001 && std::abs(f[3] - (-2.0)) < 0.001;
4944 if (!passed) {
4945 std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : floor failed" << std::endl;
4946 throw std::runtime_error("pd_test_arithmetic_series_round failed: floor failed");
4947 }
4948
4949 auto c = a.ceil();
4950 passed = std::abs(c[0] - 2.0) < 0.001 && std::abs(c[2] - 4.0) < 0.001 && std::abs(c[3] - (-1.0)) < 0.001;
4951 if (!passed) {
4952 std::cout << " [FAIL] : in pd_test_arithmetic_series_round() : ceil failed" << std::endl;
4953 throw std::runtime_error("pd_test_arithmetic_series_round failed: ceil failed");
4954 }
4955
4956 // Round with decimals
4957 pandas::Series<double> b({1.234, 2.567, 3.891});
4958 auto r2 = b.round(2);
4959 passed = std::abs(r2[0] - 1.23) < 0.001 && std::abs(r2[1] - 2.57) < 0.001;
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}
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 }
days_in_month_prop (pd_test_3_all.cpp:22045)
22035void test_dt_days_in_month() {
22036 std::cout << "========= dt.days_in_month ======================";
22037
22038 std::vector<numpy::datetime64> dates = {
22039 numpy::datetime64("2023-01-15"), // Jan = 31
22040 numpy::datetime64("2023-02-15"), // Feb 2023 = 28
22041 numpy::datetime64("2024-02-15") // Feb 2024 (leap) = 29
22042 };
22043 pandas::Series<numpy::datetime64> s(dates);
22044
22045 auto result = s.dt().days_in_month_prop();
22046 if (result[0] != 31 || result[1] != 28 || result[2] != 29) {
22047 throw std::runtime_error("dt.days_in_month: wrong values");
22048 }
22049
22050 // Also test alias
22051 auto alias = s.dt().daysinmonth();
22052 if (alias[0] != 31) {
22053 throw std::runtime_error("dt.daysinmonth: wrong values");
22054 }
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;
freq (pd_test_1_all.cpp:8233)
8223 std::cout << "========= freq property ===============================";
8224
8225 std::vector<std::optional<numpy::datetime64>> values = {
8226 numpy::datetime64(0LL, numpy::DateTimeUnit::Nanosecond),
8227 numpy::datetime64(86400000000000LL, numpy::DateTimeUnit::Nanosecond) // 1 day
8228 };
8229 pandas::DatetimeArray arr(values);
8230 pandas::DatetimeMixinIndex idx(arr);
8231
8232 // Default freq is nullopt or inferred
8233 auto f = idx.freq();
8234 std::string fs = idx.freqstr();
8235
8236 bool passed = true; // freq may or may not be set
8237 if (!passed) {
8238 std::cout << " [FAIL] : in pd_test_datetime_mixin_freq()" << std::endl;
8239 throw std::runtime_error("pd_test_datetime_mixin_freq failed");
8240 }
8241
8242 std::cout << " -> tests passed" << std::endl;
8243}
has_nat (pd_test_3_all.cpp:25049)
25039void pd_test_dt_bool_na_clean() {
25040 std::cout << "========= pd_test_dt_bool_na: clean series =============";
25041 std::vector<numpy::datetime64> dates = {
25042 numpy::datetime64("2024-01-01"),
25043 numpy::datetime64("2024-01-31"),
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");
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) {
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}
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}
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]");
round (pd_test_1_all.cpp:1688)
1678 void pd_test_floating_array_rounding() {
1679 std::cout << "========= FloatingArray: rounding ======================= ";
1680
1681 pandas::FloatingArray<double> arr({
1682 std::optional<double>(1.234),
1683 std::optional<double>(2.567),
1684 std::nullopt
1685 });
1686
1687 auto rounded = arr.round(2);
1688 if (std::abs(rounded[0].value() - 1.23) > 0.001 ||
1689 std::abs(rounded[1].value() - 2.57) > 0.001) {
1690 std::cout << " [FAIL] : in pd_test_floating_array_rounding() : round(2)" << std::endl;
1691 throw std::runtime_error("pd_test_floating_array_rounding failed: round(2)");
1692 }
1693
1694 if (!rounded.is_na(2)) {
1695 std::cout << " [FAIL] : in pd_test_floating_array_rounding() : round should preserve NA" << std::endl;
1696 throw std::runtime_error("pd_test_floating_array_rounding failed: NA preservation");
1697 }
s (pd_test_1_all.cpp:4524)
4514#include <vector>
4515#include "../pandas/pd_dataframe.h"
4516#include "../pandas/pd_series.h"
4517
4518namespace dataframe_tests {
4519 namespace dataframe_tests_aggregation {
4520
4521 void pd_test_aggregation_series_sem() {
4522 std::cout << "========= Series sem ============================";
4523
4524 pandas::Series<double> s({1.0, 2.0, 3.0, 4.0, 5.0});
4525 auto sem_val = s.sem();
4526 // std(ddof=1) = sqrt(2.5), sem = sqrt(2.5)/sqrt(5) ≈ 0.707
4527 bool passed = sem_val.has_value() && std::abs(*sem_val - 0.707) < 0.01;
4528 if (!passed) {
4529 std::cout << " [FAIL] : in pd_test_aggregation_series_sem() : sem value incorrect" << std::endl;
4530 throw std::runtime_error("pd_test_aggregation_series_sem failed: sem value incorrect");
4531 }
4532
4533 std::cout << " -> tests passed" << std::endl;
4534 }
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) {
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}
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"; }
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) {
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());
unit (pd_test_1_all.cpp:9284)
9274 data.setElementAt({0}, numpy::datetime64(1000LL, numpy::DateTimeUnit::Nanosecond));
9275 data.setElementAt({1}, numpy::datetime64(2000LL, numpy::DateTimeUnit::Nanosecond));
9276
9277 numpy::NDArray<numpy::bool_> mask(std::vector<size_t>{2});
9278 mask.setElementAt({0}, numpy::bool_(false));
9279 mask.setElementAt({1}, numpy::bool_(false));
9280
9281 pandas::DatetimeArray arr(data, mask);
9282 pandas::DatetimeTDMixin idx(arr);
9283
9284 std::string unit = idx.unit();
9285
9286 bool passed = (unit == "ns"); // nanosecond
9287 if (!passed) {
9288 std::cout << " [FAIL] : in pd_test_datetime_unit_property() : unit property check failed, got '" << unit << "'" << std::endl;
9289 throw std::runtime_error("pd_test_datetime_unit_property failed");
9290 }
9291
9292 std::cout << " -> tests passed" << std::endl;
9293}
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 }
wrap_int_result (pd_test_3_all.cpp:25102)
25092void pd_test_dt_bool_na_name_preserve() {
25093 std::cout << "========= pd_test_dt_bool_na: name preservation ========";
25094 std::vector<numpy::datetime64> dates = {
25095 numpy::datetime64("2024-01-01"),
25096 numpy::datetime64("2024-06-15")
25097 };
25098 pandas::Series<numpy::datetime64> s(dates);
25099 s.set_name("test_dates");
25100 pandas::DatetimeProperties<pandas::Series<numpy::datetime64>> dt(s);
25101 auto year_series = dt.wrap_int_result(dt.year());
25102 if (!year_series.name().has_value() || year_series.name().value() != "test_dates")
25103 throw std::runtime_error("name not preserved through wrap_int_result");
25104 std::cout << " -> tests passed" << std::endl;
25105}
25106
25107int pd_test_dt_bool_na_main() {
25108 std::cout << "====================================== running pd_test_dt_bool_na ==================================== " << std::endl;
25109 try {
25110 pd_test_dt_bool_na_clean();
25111 pd_test_dt_bool_na_with_nat();
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;