Timestamp#

class numpy::Timestamp#

numpy C++ class.

Example#

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

// Use Timestamp
Timestamp obj;
// ... operations ...

Constructors#

Signature

Location

Example

Timestamp(int64_tvalue, const std::string &tz = "")

NP_TIMESTAMP.H:155

View

Timestamp(intyear, intmonth, intday, inthour = 0, intminute = 0, intsecond = 0, intmicrosecond = 0, intnanosecond = 0, const std::string &tz = "", intfold = 0)

NP_TIMESTAMP.H:163

View

Timestamp(const std::string &ts_input, const std::string &tz = "")

NP_TIMESTAMP.H:212

View

Timestamp(const datetime64 &dt, const std::string &tz = "")

NP_TIMESTAMP.H:313

View

Timestamp(const std::chrono::time_point<std::chrono::system_clock,Duration>&tp, const std::string &tz = "")

NP_TIMESTAMP.H:331

View

Operators#

Signature

Return Type

Location

Example

timedelta64 operator-(const Timestamp &other)

timedelta64

NP_TIMESTAMP.H:1389

Timestamp operator+(const timedelta64 &delta)

Timestamp

NP_TIMESTAMP.H:1400

Timestamp operator-(const timedelta64 &delta)

Timestamp

NP_TIMESTAMP.H:1413

Timestamp & operator+=(const timedelta64 &delta)

Timestamp &

NP_TIMESTAMP.H:1425

Timestamp & operator-=(const timedelta64 &delta)

Timestamp &

NP_TIMESTAMP.H:1435

Timestamp operator+(const Timedelta &delta)

Timestamp

NP_TIMESTAMP.H:1446

Timestamp operator-(const Timedelta &delta)

Timestamp

NP_TIMESTAMP.H:1458

Timestamp & operator+=(const Timedelta &delta)

Timestamp &

NP_TIMESTAMP.H:1469

Timestamp & operator-=(const Timedelta &delta)

Timestamp &

NP_TIMESTAMP.H:1479

bool operator==(const Timestamp &other)

bool

NP_TIMESTAMP.H:1493

bool operator!=(const Timestamp &other)

bool

NP_TIMESTAMP.H:1498

bool operator<(const Timestamp &other)

bool

NP_TIMESTAMP.H:1503

bool operator<=(const Timestamp &other)

bool

NP_TIMESTAMP.H:1508

bool operator>(const Timestamp &other)

bool

NP_TIMESTAMP.H:1513

bool operator>=(const Timestamp &other)

bool

NP_TIMESTAMP.H:1518

Statistics#

Signature

Return Type

Location

Example

Timestamp max()

Timestamp

NP_TIMESTAMP.H:655

View

Timestamp min()

Timestamp

NP_TIMESTAMP.H:651

View

int minute()

int

NP_TIMESTAMP.H:699

View

int nanosecond()

int

NP_TIMESTAMP.H:717

View

Math Operations#

Signature

Return Type

Location

Example

Timestamp ceil(const std::string &freq, const std::string &ambiguous = "raise", const std::string &nonexistent = "raise")

Timestamp

NP_TIMESTAMP.H:1176

View

Timestamp floor(const std::string &freq, const std::string &ambiguous = "raise", const std::string &nonexistent = "raise")

Timestamp

NP_TIMESTAMP.H:1148

View

Timestamp round(const std::string &freq, const std::string &ambiguous = "raise", const std::string &nonexistent = "raise")

Timestamp

NP_TIMESTAMP.H:1207

View

Linear Algebra#

Signature

Return Type

Location

Example

void invalidateCache()

void

NP_TIMESTAMP.H:56

Timestamp normalize()

Timestamp

NP_TIMESTAMP.H:1233

View

I/O#

Signature

Return Type

Location

Example

datetime64 to_datetime64()

datetime64

NP_TIMESTAMP.H:861

View

double to_julian_date()

double

NP_TIMESTAMP.H:946

View

int64_t to_numpy(const std::string &dtype = "datetime64[ns]", boolcopy = false)

int64_t

NP_TIMESTAMP.H:875

View

std::tm to_pydatetime()

std::tm

NP_TIMESTAMP.H:882

View

Special Functions#

Signature

Return Type

Location

Example

Timestamp combine(const std::tuple<int,int,int>&date, const std::tuple<int,int,int,int>&time)

Timestamp

NP_TIMESTAMP.H:389

View

Type Checking#

Signature

Return Type

Location

Example

bool is_leap_year()

bool

NP_TIMESTAMP.H:795

View

bool is_month_end()

bool

NP_TIMESTAMP.H:807

View

bool is_month_start()

bool

NP_TIMESTAMP.H:801

View

bool is_quarter_end()

bool

NP_TIMESTAMP.H:819

View

bool is_quarter_start()

bool

NP_TIMESTAMP.H:813

View

bool is_year_end()

bool

NP_TIMESTAMP.H:831

View

bool is_year_start()

bool

NP_TIMESTAMP.H:825

View

Other Methods#

Signature

Return Type

Location

Example

Timestamp NaT()

Timestamp

NP_TIMESTAMP.H:659

View

Timestamp as_unit(const std::string &unit, boolround_ok = true)

Timestamp

NP_TIMESTAMP.H:1286

View

datetime64 asm8()

datetime64

NP_TIMESTAMP.H:867

View

Timestamp astimezone(const std::string &tz_str)

Timestamp

NP_TIMESTAMP.H:1362

View

int64_t componentsToNanos(intyear, intmonth, intday, inthour, intminute, intsecond, intmicrosecond, intnanosecond)

int64_t

NP_TIMESTAMP.H:104

void computeComponents()

void

NP_TIMESTAMP.H:60

std::string ctime()

std::string

NP_TIMESTAMP.H:1040

View

int day()

int

NP_TIMESTAMP.H:687

View

std::string day_name(const std::string &locale = "")

std::string

NP_TIMESTAMP.H:1045

View

int day_of_week()

int

NP_TIMESTAMP.H:749

View

int day_of_year()

int

NP_TIMESTAMP.H:766

View

int dayofweek()

int

NP_TIMESTAMP.H:732

View

int dayofyear()

int

NP_TIMESTAMP.H:752

View

int days_in_month()

int

NP_TIMESTAMP.H:785

View

timedelta64 dst()

timedelta64

NP_TIMESTAMP.H:1376

View

int fold()

int

NP_TIMESTAMP.H:852

View

Timestamp fromisocalendar(intiso_year, intiso_week, intiso_weekday)

Timestamp

NP_TIMESTAMP.H:398

View

Timestamp fromisoformat(const std::string &date_string)

Timestamp

NP_TIMESTAMP.H:428

View

Timestamp fromordinal(int64_tordinal, const std::string &tz = "")

Timestamp

NP_TIMESTAMP.H:380

View

Timestamp fromtimestamp(doublets, const std::string &tz = "")

Timestamp

NP_TIMESTAMP.H:369

View

int hour()

int

NP_TIMESTAMP.H:693

View

bool isNaT()

bool

NP_TIMESTAMP.H:667

View

std::string isoformat(charsep = 'T', const std::string &timespec = "auto")

std::string

NP_TIMESTAMP.H:978

View

int isoweekday()

int

NP_TIMESTAMP.H:1128

View

int microsecond()

int

NP_TIMESTAMP.H:711

View

int month()

int

NP_TIMESTAMP.H:681

View

std::string month_name(const std::string &locale = "")

std::string

NP_TIMESTAMP.H:1053

View

Timestamp now(const std::string &tz = "")

Timestamp

NP_TIMESTAMP.H:350

View

int64_t parseFrequencyToNanos(const std::string &freq)

int64_t

NP_TIMESTAMP.H:133

int quarter()

int

NP_TIMESTAMP.H:778

View

Timestamp replace(intnew_year = -1, intnew_month = -1, intnew_day = -1, intnew_hour = -1, intnew_minute = -1, intnew_second = -1, intnew_microsecond = -1, intnew_nanosecond = -1, const std::string &new_tzinfo = "", intnew_fold = -1)

Timestamp

NP_TIMESTAMP.H:1255

View

int second()

int

NP_TIMESTAMP.H:705

View

std::string strftime(const std::string &format)

std::string

NP_TIMESTAMP.H:1031

View

Timestamp strptime(const std::string &date_string, const std::string &format)

Timestamp

NP_TIMESTAMP.H:455

View

double timestamp()

double

NP_TIMESTAMP.H:901

View

std::string toString()

std::string

NP_TIMESTAMP.H:973

View

Timestamp today(const std::string &tz = "")

Timestamp

NP_TIMESTAMP.H:358

View

int toordinal()

int

NP_TIMESTAMP.H:955

View

std::string tz()

std::string

NP_TIMESTAMP.H:841

View

Timestamp tz_convert(const std::string &tz_str)

Timestamp

NP_TIMESTAMP.H:1340

View

Timestamp tz_localize(const std::string &tz_str)

Timestamp

NP_TIMESTAMP.H:1315

View

std::string tzinfo()

std::string

NP_TIMESTAMP.H:845

View

std::string tzname()

std::string

NP_TIMESTAMP.H:847

View

Timestamp utcfromtimestamp(doublets)

Timestamp

NP_TIMESTAMP.H:375

View

Timestamp utcnow()

Timestamp

NP_TIMESTAMP.H:364

View

timedelta64 utcoffset()

timedelta64

NP_TIMESTAMP.H:1367

View

int64_t value()

int64_t

NP_TIMESTAMP.H:723

View

int week()

int

NP_TIMESTAMP.H:769

View

int weekday()

int

NP_TIMESTAMP.H:1133

View

int weekofyear()

int

NP_TIMESTAMP.H:775

int year()

int

NP_TIMESTAMP.H:675

View

Code Examples#

The following examples are extracted from the test suite.

Timestamp (np_test_5_all.cpp:23235)
23225      std::cout << " -> tests passed" << std::endl;
23226    }
23227
23228    // Test untested Timestamp methods: constructor(int64_t), utcfromtimestamp, utctimetuple, timetz
23229    void np_test_timestamp_untested_methods() {
23230      std::cout << "========= timestamp: untested methods (int64_t ctor, utcfromtimestamp, utctimetuple, timetz) ==";
23231
23232      auto pass = true;
23233      std::string fail_msg;
23234
23235      // Test 1: Timestamp(int64_t value, tz) constructor - from nanoseconds since epoch
23236      // Verify round-trip: construct from nanos, convert back to value, should match
23237      // 1718454645000000000LL = 2024-06-15 12:30:45 UTC (verified with Python)
23238      int64_t nanos = 1718454645000000000LL;
23239      numpy::Timestamp ts_from_nanos(nanos, "UTC");  // Construct with UTC timezone
23240      // Verify the stored value matches input
23241      if (ts_from_nanos.value() != nanos) {
23242        pass = false;
23243        fail_msg = "Timestamp(int64_t) value() should return input nanos";
23244      }
23245      // Verify we can extract correct UTC components
Timestamp (np_test_5_all.cpp:23235)
23225      std::cout << " -> tests passed" << std::endl;
23226    }
23227
23228    // Test untested Timestamp methods: constructor(int64_t), utcfromtimestamp, utctimetuple, timetz
23229    void np_test_timestamp_untested_methods() {
23230      std::cout << "========= timestamp: untested methods (int64_t ctor, utcfromtimestamp, utctimetuple, timetz) ==";
23231
23232      auto pass = true;
23233      std::string fail_msg;
23234
23235      // Test 1: Timestamp(int64_t value, tz) constructor - from nanoseconds since epoch
23236      // Verify round-trip: construct from nanos, convert back to value, should match
23237      // 1718454645000000000LL = 2024-06-15 12:30:45 UTC (verified with Python)
23238      int64_t nanos = 1718454645000000000LL;
23239      numpy::Timestamp ts_from_nanos(nanos, "UTC");  // Construct with UTC timezone
23240      // Verify the stored value matches input
23241      if (ts_from_nanos.value() != nanos) {
23242        pass = false;
23243        fail_msg = "Timestamp(int64_t) value() should return input nanos";
23244      }
23245      // Verify we can extract correct UTC components
Timestamp (np_test_5_all.cpp:23235)
23225      std::cout << " -> tests passed" << std::endl;
23226    }
23227
23228    // Test untested Timestamp methods: constructor(int64_t), utcfromtimestamp, utctimetuple, timetz
23229    void np_test_timestamp_untested_methods() {
23230      std::cout << "========= timestamp: untested methods (int64_t ctor, utcfromtimestamp, utctimetuple, timetz) ==";
23231
23232      auto pass = true;
23233      std::string fail_msg;
23234
23235      // Test 1: Timestamp(int64_t value, tz) constructor - from nanoseconds since epoch
23236      // Verify round-trip: construct from nanos, convert back to value, should match
23237      // 1718454645000000000LL = 2024-06-15 12:30:45 UTC (verified with Python)
23238      int64_t nanos = 1718454645000000000LL;
23239      numpy::Timestamp ts_from_nanos(nanos, "UTC");  // Construct with UTC timezone
23240      // Verify the stored value matches input
23241      if (ts_from_nanos.value() != nanos) {
23242        pass = false;
23243        fail_msg = "Timestamp(int64_t) value() should return input nanos";
23244      }
23245      // Verify we can extract correct UTC components
Timestamp (np_test_5_all.cpp:23235)
23225      std::cout << " -> tests passed" << std::endl;
23226    }
23227
23228    // Test untested Timestamp methods: constructor(int64_t), utcfromtimestamp, utctimetuple, timetz
23229    void np_test_timestamp_untested_methods() {
23230      std::cout << "========= timestamp: untested methods (int64_t ctor, utcfromtimestamp, utctimetuple, timetz) ==";
23231
23232      auto pass = true;
23233      std::string fail_msg;
23234
23235      // Test 1: Timestamp(int64_t value, tz) constructor - from nanoseconds since epoch
23236      // Verify round-trip: construct from nanos, convert back to value, should match
23237      // 1718454645000000000LL = 2024-06-15 12:30:45 UTC (verified with Python)
23238      int64_t nanos = 1718454645000000000LL;
23239      numpy::Timestamp ts_from_nanos(nanos, "UTC");  // Construct with UTC timezone
23240      // Verify the stored value matches input
23241      if (ts_from_nanos.value() != nanos) {
23242        pass = false;
23243        fail_msg = "Timestamp(int64_t) value() should return input nanos";
23244      }
23245      // Verify we can extract correct UTC components
Timestamp (np_test_5_all.cpp:23235)
23225      std::cout << " -> tests passed" << std::endl;
23226    }
23227
23228    // Test untested Timestamp methods: constructor(int64_t), utcfromtimestamp, utctimetuple, timetz
23229    void np_test_timestamp_untested_methods() {
23230      std::cout << "========= timestamp: untested methods (int64_t ctor, utcfromtimestamp, utctimetuple, timetz) ==";
23231
23232      auto pass = true;
23233      std::string fail_msg;
23234
23235      // Test 1: Timestamp(int64_t value, tz) constructor - from nanoseconds since epoch
23236      // Verify round-trip: construct from nanos, convert back to value, should match
23237      // 1718454645000000000LL = 2024-06-15 12:30:45 UTC (verified with Python)
23238      int64_t nanos = 1718454645000000000LL;
23239      numpy::Timestamp ts_from_nanos(nanos, "UTC");  // Construct with UTC timezone
23240      // Verify the stored value matches input
23241      if (ts_from_nanos.value() != nanos) {
23242        pass = false;
23243        fail_msg = "Timestamp(int64_t) value() should return input nanos";
23244      }
23245      // Verify we can extract correct UTC components
max (np_test_1_all.cpp:7274)
7264    if (sizeof(uintp) == sizeof(void*)) {
7265        // std::cout << "                -> uintp size matches pointer size";
7266    } else {
7267        // std::cout << "  ✗ uintp size doesn't match pointer size" << std::endl;
7268    }
7269
7270    // Test range limits
7271    // std::cout << "Range Information:" << std::endl;
7272    // std::cout << "  intp min: " << std::numeric_limits<intp>::min() << std::endl;
7273    // std::cout << "  intp max: " << std::numeric_limits<intp>::max() << std::endl;
7274    // std::cout << "  uintp max: " << std::numeric_limits<uintp>::max() << std::endl;
7275    // std::cout << "  longdouble digits: " << std::numeric_limits<longdouble>::digits << std::endl;
7276
7277    std::cout << " -> tests passed" << std::endl;
7278}
7279
7280void testComplexArithmeticExtendedTypes() {
7281    std::cout << "========= testComplexArithmeticExtendedTypes =======================";
7282
7283    clongdouble c1(3.0L, 4.0L);  // 3 + 4i
min (np_test_1_all.cpp:2350)
2340        if (i % 3 == 0) {
2341            large_array.setElementAt({i}, object_(static_cast<int>(i)));
2342        } else if (i % 3 == 1) {
2343            large_array.setElementAt({i}, object_(static_cast<double>(i) * 0.5));
2344        } else {
2345            large_array.setElementAt({i}, object_(std::string("str") + std::to_string(i)));
2346        }
2347    }
2348
2349    // Verify pattern
2350    for (size_t i = 0; i < std::min(large_size, size_t(100)); ++i) {  // Check first 100
2351        object_ obj = large_array.getElementAt({i});
2352        if (i % 3 == 0) {
2353            if (!(obj.is_type<int>())) {
2354                std::string description = std::string("testArrayEdgeCases():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(obj.is_type<int>())";
2355                std::cout << std::string("[FAIL] ") + description << std::endl;
2356                throw std::runtime_error(description);
2357            }
2358        } else if (i % 3 == 1) {
2359            if (!(obj.is_type<double>())) {
2360                std::string description = std::string("unknown_function():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(obj.is_type<double>())";
minute (np_test_5_all.cpp:22277)
22267      // Default constructor (NaT)
22268      numpy::Timestamp nat;
22269      if (!nat.isNaT()) {
22270        pass = false;
22271        fail_msg = "Default constructor should create NaT";
22272      }
22273
22274      // Component constructor
22275      numpy::Timestamp ts1(2024, 6, 15, 14, 30, 45);
22276      if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
22277          ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
22278        pass = false;
22279        fail_msg = "Component constructor values incorrect";
22280      }
22281
22282      // With microseconds and nanoseconds
22283      numpy::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
22284      if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
22285        pass = false;
22286        fail_msg = "Microsecond/nanosecond values incorrect";
22287      }
nanosecond (np_test_5_all.cpp:22284)
22274      // Component constructor
22275      numpy::Timestamp ts1(2024, 6, 15, 14, 30, 45);
22276      if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
22277          ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
22278        pass = false;
22279        fail_msg = "Component constructor values incorrect";
22280      }
22281
22282      // With microseconds and nanoseconds
22283      numpy::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
22284      if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
22285        pass = false;
22286        fail_msg = "Microsecond/nanosecond values incorrect";
22287      }
22288
22289      // String constructor - ISO format
22290      numpy::Timestamp ts3("2024-06-15T14:30:45");
22291      if (ts3.year() != 2024 || ts3.month() != 6 || ts3.day() != 15) {
22292        pass = false;
22293        fail_msg = "String constructor parse failed";
22294      }
ceil (np_test_2_all.cpp:5735)
5725          throw std::runtime_error(description);
5726      }
5727      if (!(approx_equal(floor_result.getElementAt({ 5 }), std::floor(2.7)))) {
5728          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(floor_result.getElementAt({ 5 }), std::floor(2.7)))";
5729          std::cout << std::string("[FAIL] ") + description << std::endl;
5730          throw std::runtime_error(description);
5731      }
5732      // std::cout << "[OK] floor function works correctly\n";
5733
5734      // Test ceil
5735      auto ceil_result = ceil(values);
5736      if (!(approx_equal(ceil_result.getElementAt({ 0 }), std::ceil(-2.7)))) {
5737          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(ceil_result.getElementAt({ 0 }), std::ceil(-2.7)))";
5738          std::cout << std::string("[FAIL] ") + description << std::endl;
5739          throw std::runtime_error(description);
5740      }
5741      if (!(approx_equal(ceil_result.getElementAt({ 5 }), std::ceil(2.7)))) {
5742          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(ceil_result.getElementAt({ 5 }), std::ceil(2.7)))";
5743          std::cout << std::string("[FAIL] ") + description << std::endl;
5744          throw std::runtime_error(description);
5745      }
floor (np_test_2_all.cpp:5721)
5711          throw std::runtime_error(description);
5712      }
5713      if (!(approx_equal(round_result.getElementAt({ 5 }), std::round(2.7)))) {
5714          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(round_result.getElementAt({ 5 }), std::round(2.7)))";
5715          std::cout << std::string("[FAIL] ") + description << std::endl;
5716          throw std::runtime_error(description);
5717      }
5718      // std::cout << "[OK] round function works correctly\n";
5719
5720      // Test floor
5721      auto floor_result = floor(values);
5722      if (!(approx_equal(floor_result.getElementAt({ 0 }), std::floor(-2.7)))) {
5723          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(floor_result.getElementAt({ 0 }), std::floor(-2.7)))";
5724          std::cout << std::string("[FAIL] ") + description << std::endl;
5725          throw std::runtime_error(description);
5726      }
5727      if (!(approx_equal(floor_result.getElementAt({ 5 }), std::floor(2.7)))) {
5728          std::string description = std::string("testRoundingFunctions():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(approx_equal(floor_result.getElementAt({ 5 }), std::floor(2.7)))";
5729          std::cout << std::string("[FAIL] ") + description << std::endl;
5730          throw std::runtime_error(description);
5731      }
round (np_test_1_all.cpp:23769)
23759          throw std::runtime_error(description);
23760      }
23761      if (!(power_scalar_result.getShape() == array.getShape())) {
23762          std::string description = std::string("testMathFunctionSignatures():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(power_scalar_result.getShape() == array.getShape())";
23763          std::cout << std::string("[FAIL] ") + description << std::endl;
23764          throw std::runtime_error(description);
23765      }
23766      // std::cout << "[OK] Power functions have correct signatures\n";
23767
23768      // Test rounding functions with new decimals parameter
23769      auto round_result = round(array);        // Default decimals=0
23770      auto round_decimals_result = round(array, 2);  // With decimals
23771      if (!(round_result.getShape() == array.getShape())) {
23772          std::string description = std::string("testMathFunctionSignatures():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(round_result.getShape() == array.getShape())";
23773          std::cout << std::string("[FAIL] ") + description << std::endl;
23774          throw std::runtime_error(description);
23775      }
23776      if (!(round_decimals_result.getShape() == array.getShape())) {
23777          std::string description = std::string("testMathFunctionSignatures():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(round_decimals_result.getShape() == array.getShape())";
23778          std::cout << std::string("[FAIL] ") + description << std::endl;
23779          throw std::runtime_error(description);
normalize (np_test_5_all.cpp:22908)
22898        fail_msg = "ceil to hour failed";
22899      }
22900
22901      // round to hour (37 minutes -> round up)
22902      numpy::Timestamp rounded_h = ts.round("h");
22903      if (rounded_h.hour() != 15) {
22904        pass = false;
22905        fail_msg = "round to hour should be 15 (37 > 30)";
22906      }
22907
22908      // normalize (floor to day)
22909      numpy::Timestamp normalized = ts.normalize();
22910      if (normalized.hour() != 0 || normalized.minute() != 0 || normalized.second() != 0) {
22911        pass = false;
22912        fail_msg = "normalize should be midnight";
22913      }
22914
22915      // floor to day
22916      numpy::Timestamp floored_d = ts.floor("D");
22917      if (floored_d.day() != 15 || floored_d.hour() != 0) {
22918        pass = false;
to_datetime64 (np_test_5_all.cpp:22746)
22736    void np_test_timestamp_conversions() {
22737      std::cout << "========= timestamp: conversion methods ==========================";
22738
22739      auto pass = true;
22740      std::string fail_msg;
22741
22742      numpy::Timestamp ts(2024, 6, 15, 12, 30, 45, 123456, 789);
22743
22744      // to_datetime64
22745      numpy::datetime64 dt = ts.to_datetime64();
22746      if (dt.isNaT()) { pass = false; fail_msg = "to_datetime64 should not return NaT"; }
22747
22748      // asm8 alias
22749      numpy::datetime64 asm8 = ts.asm8();
22750      if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; }
22751
22752      // to_numpy
22753      int64_t value = ts.to_numpy();
22754      if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; }
to_julian_date (np_test_5_all.cpp:22778)
22768      if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; }
22769
22770      // date/time tuples
22771      auto [dy, dm, dd] = ts.date();
22772      if (dy != 2024) { pass = false; fail_msg = "date tuple year"; }
22773
22774      auto [th, tmi, ts2, tus] = ts.time();
22775      if (th != 12) { pass = false; fail_msg = "time tuple hour"; }
22776
22777      // Julian date
22778      double jd = ts.to_julian_date();
22779      if (jd < 2400000) { pass = false; fail_msg = "Julian date should be reasonable"; }
22780
22781      // Ordinal
22782      int ord = ts.toordinal();
22783      if (ord <= 0) { pass = false; fail_msg = "Ordinal should be positive"; }
22784
22785      if (!pass) {
22786        std::cout << "  [FAIL] : in np_test_timestamp_conversions() : " << fail_msg;
22787        throw std::runtime_error("np_test_timestamp_conversions failed: " + fail_msg);
22788      }
to_numpy (np_test_5_all.cpp:21464)
21454        numpy::timedelta64 td64 = td.to_timedelta64(numpy::DateTimeUnit::Hour);
21455        if (td64.getValue() != 24) {
21456            std::cout << "[FAIL] np_test_timedelta_conversions: to_timedelta64(Hour) expected 24, got "
21457                      << td64.getValue() << std::endl;
21458            errors++;
21459        }
21460    }
21461
21462    // to_numpy
21463    {
21464        int64_t nanos = td.to_numpy();
21465        if (nanos != numpy::Timedelta::NANOS_PER_DAY) {
21466            std::cout << "[FAIL] np_test_timedelta_conversions: to_numpy expected "
21467                      << numpy::Timedelta::NANOS_PER_DAY << ", got " << nanos << std::endl;
21468            errors++;
21469        }
21470    }
21471
21472    // to_chrono
21473    {
21474        std::chrono::nanoseconds dur = td.to_chrono();
to_pydatetime (np_test_5_all.cpp:22758)
22748      // asm8 alias
22749      numpy::datetime64 asm8 = ts.asm8();
22750      if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; }
22751
22752      // to_numpy
22753      int64_t value = ts.to_numpy();
22754      if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; }
22755
22756      // to_pydatetime
22757      std::tm tm = ts.to_pydatetime();
22758      if (tm.tm_year != 124) { pass = false; fail_msg = "tm_year should be 124 (2024-1900)"; }
22759      if (tm.tm_mon != 5) { pass = false; fail_msg = "tm_mon should be 5 (June)"; }
22760
22761      // timestamp
22762      double posix = ts.timestamp();
22763      if (posix <= 0) { pass = false; fail_msg = "POSIX timestamp should be positive"; }
22764
22765      // timetuple
22766      auto [y, mo, d, h, mi, s] = ts.timetuple();
22767      if (y != 2024 || mo != 6) { pass = false; fail_msg = "timetuple values incorrect"; }
combine (np_test_5_all.cpp:22364)
22354      }
22355
22356      // fromordinal
22357      numpy::Timestamp from_ord = numpy::Timestamp::fromordinal(738678);
22358      if (from_ord.isNaT()) {
22359        pass = false;
22360        fail_msg = "fromordinal should not return NaT";
22361      }
22362
22363      // combine
22364      numpy::Timestamp combined = numpy::Timestamp::combine({2024, 6, 15}, {12, 30, 45, 0});
22365      if (combined.year() != 2024 || combined.hour() != 12) {
22366        pass = false;
22367        fail_msg = "combine() values incorrect";
22368      }
22369
22370      // Static values
22371      numpy::Timestamp min_ts = numpy::Timestamp::min();
22372      numpy::Timestamp max_ts = numpy::Timestamp::max();
22373      numpy::Timestamp nat_ts = numpy::Timestamp::NaT();
22374      if (min_ts.isNaT() || max_ts.isNaT() || !nat_ts.isNaT()) {
is_leap_year (np_test_5_all.cpp:22668)
22658    // ============================================================================
22659
22660    void np_test_timestamp_booleans() {
22661      std::cout << "========= timestamp: boolean properties ==========================";
22662
22663      auto pass = true;
22664      std::string fail_msg;
22665
22666      // Leap year
22667      numpy::Timestamp leap(2024, 2, 29);
22668      if (!leap.is_leap_year()) { pass = false; fail_msg = "2024 is a leap year"; }
22669
22670      numpy::Timestamp non_leap(2023, 2, 28);
22671      if (non_leap.is_leap_year()) { pass = false; fail_msg = "2023 is not a leap year"; }
22672
22673      // Year start/end
22674      numpy::Timestamp jan1(2024, 1, 1);
22675      if (!jan1.is_year_start()) { pass = false; fail_msg = "Jan 1 is year start"; }
22676      if (!jan1.is_month_start()) { pass = false; fail_msg = "Jan 1 is month start"; }
22677      if (!jan1.is_quarter_start()) { pass = false; fail_msg = "Jan 1 is quarter start"; }
is_month_end (np_test_5_all.cpp:22681)
22671      if (non_leap.is_leap_year()) { pass = false; fail_msg = "2023 is not a leap year"; }
22672
22673      // Year start/end
22674      numpy::Timestamp jan1(2024, 1, 1);
22675      if (!jan1.is_year_start()) { pass = false; fail_msg = "Jan 1 is year start"; }
22676      if (!jan1.is_month_start()) { pass = false; fail_msg = "Jan 1 is month start"; }
22677      if (!jan1.is_quarter_start()) { pass = false; fail_msg = "Jan 1 is quarter start"; }
22678
22679      numpy::Timestamp dec31(2024, 12, 31);
22680      if (!dec31.is_year_end()) { pass = false; fail_msg = "Dec 31 is year end"; }
22681      if (!dec31.is_month_end()) { pass = false; fail_msg = "Dec 31 is month end"; }
22682      if (!dec31.is_quarter_end()) { pass = false; fail_msg = "Dec 31 is quarter end"; }
22683
22684      // Quarter boundaries
22685      numpy::Timestamp mar31(2024, 3, 31);
22686      if (!mar31.is_quarter_end()) { pass = false; fail_msg = "Mar 31 is quarter end"; }
22687
22688      numpy::Timestamp apr1(2024, 4, 1);
22689      if (!apr1.is_quarter_start()) { pass = false; fail_msg = "Apr 1 is quarter start"; }
22690
22691      if (!pass) {
is_month_start (np_test_5_all.cpp:22676)
22666      // Leap year
22667      numpy::Timestamp leap(2024, 2, 29);
22668      if (!leap.is_leap_year()) { pass = false; fail_msg = "2024 is a leap year"; }
22669
22670      numpy::Timestamp non_leap(2023, 2, 28);
22671      if (non_leap.is_leap_year()) { pass = false; fail_msg = "2023 is not a leap year"; }
22672
22673      // Year start/end
22674      numpy::Timestamp jan1(2024, 1, 1);
22675      if (!jan1.is_year_start()) { pass = false; fail_msg = "Jan 1 is year start"; }
22676      if (!jan1.is_month_start()) { pass = false; fail_msg = "Jan 1 is month start"; }
22677      if (!jan1.is_quarter_start()) { pass = false; fail_msg = "Jan 1 is quarter start"; }
22678
22679      numpy::Timestamp dec31(2024, 12, 31);
22680      if (!dec31.is_year_end()) { pass = false; fail_msg = "Dec 31 is year end"; }
22681      if (!dec31.is_month_end()) { pass = false; fail_msg = "Dec 31 is month end"; }
22682      if (!dec31.is_quarter_end()) { pass = false; fail_msg = "Dec 31 is quarter end"; }
22683
22684      // Quarter boundaries
22685      numpy::Timestamp mar31(2024, 3, 31);
22686      if (!mar31.is_quarter_end()) { pass = false; fail_msg = "Mar 31 is quarter end"; }
is_quarter_end (np_test_5_all.cpp:22682)
22672      // Year start/end
22673      numpy::Timestamp jan1(2024, 1, 1);
22674      if (!jan1.is_year_start()) { pass = false; fail_msg = "Jan 1 is year start"; }
22675      if (!jan1.is_month_start()) { pass = false; fail_msg = "Jan 1 is month start"; }
22676      if (!jan1.is_quarter_start()) { pass = false; fail_msg = "Jan 1 is quarter start"; }
22677
22678      numpy::Timestamp dec31(2024, 12, 31);
22679      if (!dec31.is_year_end()) { pass = false; fail_msg = "Dec 31 is year end"; }
22680      if (!dec31.is_month_end()) { pass = false; fail_msg = "Dec 31 is month end"; }
22681      if (!dec31.is_quarter_end()) { pass = false; fail_msg = "Dec 31 is quarter end"; }
22682
22683      // Quarter boundaries
22684      numpy::Timestamp mar31(2024, 3, 31);
22685      if (!mar31.is_quarter_end()) { pass = false; fail_msg = "Mar 31 is quarter end"; }
22686
22687      numpy::Timestamp apr1(2024, 4, 1);
22688      if (!apr1.is_quarter_start()) { pass = false; fail_msg = "Apr 1 is quarter start"; }
22689
22690      if (!pass) {
22691        std::cout << "  [FAIL] : in np_test_timestamp_booleans() : " << fail_msg;
is_quarter_start (np_test_5_all.cpp:22677)
22667      numpy::Timestamp leap(2024, 2, 29);
22668      if (!leap.is_leap_year()) { pass = false; fail_msg = "2024 is a leap year"; }
22669
22670      numpy::Timestamp non_leap(2023, 2, 28);
22671      if (non_leap.is_leap_year()) { pass = false; fail_msg = "2023 is not a leap year"; }
22672
22673      // Year start/end
22674      numpy::Timestamp jan1(2024, 1, 1);
22675      if (!jan1.is_year_start()) { pass = false; fail_msg = "Jan 1 is year start"; }
22676      if (!jan1.is_month_start()) { pass = false; fail_msg = "Jan 1 is month start"; }
22677      if (!jan1.is_quarter_start()) { pass = false; fail_msg = "Jan 1 is quarter start"; }
22678
22679      numpy::Timestamp dec31(2024, 12, 31);
22680      if (!dec31.is_year_end()) { pass = false; fail_msg = "Dec 31 is year end"; }
22681      if (!dec31.is_month_end()) { pass = false; fail_msg = "Dec 31 is month end"; }
22682      if (!dec31.is_quarter_end()) { pass = false; fail_msg = "Dec 31 is quarter end"; }
22683
22684      // Quarter boundaries
22685      numpy::Timestamp mar31(2024, 3, 31);
22686      if (!mar31.is_quarter_end()) { pass = false; fail_msg = "Mar 31 is quarter end"; }
is_year_end (np_test_5_all.cpp:22680)
22670      numpy::Timestamp non_leap(2023, 2, 28);
22671      if (non_leap.is_leap_year()) { pass = false; fail_msg = "2023 is not a leap year"; }
22672
22673      // Year start/end
22674      numpy::Timestamp jan1(2024, 1, 1);
22675      if (!jan1.is_year_start()) { pass = false; fail_msg = "Jan 1 is year start"; }
22676      if (!jan1.is_month_start()) { pass = false; fail_msg = "Jan 1 is month start"; }
22677      if (!jan1.is_quarter_start()) { pass = false; fail_msg = "Jan 1 is quarter start"; }
22678
22679      numpy::Timestamp dec31(2024, 12, 31);
22680      if (!dec31.is_year_end()) { pass = false; fail_msg = "Dec 31 is year end"; }
22681      if (!dec31.is_month_end()) { pass = false; fail_msg = "Dec 31 is month end"; }
22682      if (!dec31.is_quarter_end()) { pass = false; fail_msg = "Dec 31 is quarter end"; }
22683
22684      // Quarter boundaries
22685      numpy::Timestamp mar31(2024, 3, 31);
22686      if (!mar31.is_quarter_end()) { pass = false; fail_msg = "Mar 31 is quarter end"; }
22687
22688      numpy::Timestamp apr1(2024, 4, 1);
22689      if (!apr1.is_quarter_start()) { pass = false; fail_msg = "Apr 1 is quarter start"; }
is_year_start (np_test_5_all.cpp:22675)
22665      // Leap year
22666      numpy::Timestamp leap(2024, 2, 29);
22667      if (!leap.is_leap_year()) { pass = false; fail_msg = "2024 is a leap year"; }
22668
22669      numpy::Timestamp non_leap(2023, 2, 28);
22670      if (non_leap.is_leap_year()) { pass = false; fail_msg = "2023 is not a leap year"; }
22671
22672      // Year start/end
22673      numpy::Timestamp jan1(2024, 1, 1);
22674      if (!jan1.is_year_start()) { pass = false; fail_msg = "Jan 1 is year start"; }
22675      if (!jan1.is_month_start()) { pass = false; fail_msg = "Jan 1 is month start"; }
22676      if (!jan1.is_quarter_start()) { pass = false; fail_msg = "Jan 1 is quarter start"; }
22677
22678      numpy::Timestamp dec31(2024, 12, 31);
22679      if (!dec31.is_year_end()) { pass = false; fail_msg = "Dec 31 is year end"; }
22680      if (!dec31.is_month_end()) { pass = false; fail_msg = "Dec 31 is month end"; }
22681      if (!dec31.is_quarter_end()) { pass = false; fail_msg = "Dec 31 is quarter end"; }
22682
22683      // Quarter boundaries
22684      numpy::Timestamp mar31(2024, 3, 31);
NaT (np_test_1_all.cpp:7020)
7010        // std::cout << april_2024.getElementAt({i}).toString() << " ";
7011    }
7012    // std::cout << std::endl;
7013
7014        std::cout << " -> tests passed" << std::endl;
7015}
7016
7017void testNaTHandlingDateTime() {
7018    std::cout << "========= testNaTHandlingDateTime =======================";
7019
7020    datetime64 nat_dt = datetime64::NaT();
7021    timedelta64 nat_td = timedelta64::NaT();
7022
7023    // std::cout << "NaT datetime: " << nat_dt.toString() << std::endl;
7024    // std::cout << "NaT timedelta: " << nat_td.toString() << std::endl;
7025
7026    datetime64 valid_date("2024-01-01");
7027
7028    // NaT arithmetic
7029    datetime64 result1 = valid_date + nat_td;
7030    datetime64 result2 = nat_dt + timedelta64(1, DateTimeUnit::Day);
as_unit (np_test_5_all.cpp:22957)
22947      }
22948
22949      // Replace multiple
22950      numpy::Timestamp multi = ts.replace(2025, 7, 20, 14);
22951      if (multi.year() != 2025 || multi.month() != 7 || multi.day() != 20 || multi.hour() != 14) {
22952        pass = false;
22953        fail_msg = "Replace multiple values failed";
22954      }
22955
22956      // as_unit
22957      numpy::Timestamp as_unit_ts = ts.as_unit("ns");
22958      if (as_unit_ts.isNaT()) {
22959        pass = false;
22960        fail_msg = "as_unit should not return NaT";
22961      }
22962
22963      if (!pass) {
22964        std::cout << "  [FAIL] : in np_test_timestamp_replace() : " << fail_msg;
22965        throw std::runtime_error("np_test_timestamp_replace failed: " + fail_msg);
22966      }
asm8 (np_test_5_all.cpp:22750)
22740      auto pass = true;
22741      std::string fail_msg;
22742
22743      numpy::Timestamp ts(2024, 6, 15, 12, 30, 45, 123456, 789);
22744
22745      // to_datetime64
22746      numpy::datetime64 dt = ts.to_datetime64();
22747      if (dt.isNaT()) { pass = false; fail_msg = "to_datetime64 should not return NaT"; }
22748
22749      // asm8 alias
22750      numpy::datetime64 asm8 = ts.asm8();
22751      if (asm8.isNaT()) { pass = false; fail_msg = "asm8 should not return NaT"; }
22752
22753      // to_numpy
22754      int64_t value = ts.to_numpy();
22755      if (value == 0) { pass = false; fail_msg = "to_numpy should return non-zero"; }
22756
22757      // to_pydatetime
22758      std::tm tm = ts.to_pydatetime();
22759      if (tm.tm_year != 124) { pass = false; fail_msg = "tm_year should be 124 (2024-1900)"; }
22760      if (tm.tm_mon != 5) { pass = false; fail_msg = "tm_mon should be 5 (June)"; }
astimezone (np_test_5_all.cpp:22996)
22986        fail_msg = "tz_localize should set timezone";
22987      }
22988
22989      // tz_convert
22990      numpy::Timestamp converted = localized.tz_convert("Europe/London");
22991      if (converted.tz() != "Europe/London") {
22992        pass = false;
22993        fail_msg = "tz_convert should change timezone";
22994      }
22995
22996      // astimezone (alias)
22997      numpy::Timestamp ast = localized.astimezone("UTC");
22998      if (ast.tz() != "UTC") {
22999        pass = false;
23000        fail_msg = "astimezone should convert to UTC";
23001      }
23002
23003      // utcoffset
23004      numpy::timedelta64 offset = localized.utcoffset();
23005      if (offset.isNaT()) {
23006        pass = false;
ctime (np_test_5_all.cpp:22822)
22812      // isoformat with space separator
22813      std::string iso_space = ts.isoformat(' ');
22814      if (iso_space.find(" ") == std::string::npos) { pass = false; fail_msg = "isoformat with space separator"; }
22815
22816      // strftime
22817      std::string fmt = ts.strftime("%Y/%m/%d");
22818      if (fmt != "2024/06/15") { pass = false; fail_msg = "strftime format"; }
22819
22820      // ctime
22821      std::string ct = ts.ctime();
22822      if (ct.find("2024") == std::string::npos) { pass = false; fail_msg = "ctime should contain year"; }
22823
22824      // day_name
22825      std::string dayname = ts.day_name();
22826      if (dayname != "Saturday") { pass = false; fail_msg = "2024-06-15 is Saturday"; }
22827
22828      // month_name
22829      std::string monthname = ts.month_name();
22830      if (monthname != "June") { pass = false; fail_msg = "Month should be June"; }
day (np_test_5_all.cpp:22276)
22266      // Default constructor (NaT)
22267      numpy::Timestamp nat;
22268      if (!nat.isNaT()) {
22269        pass = false;
22270        fail_msg = "Default constructor should create NaT";
22271      }
22272
22273      // Component constructor
22274      numpy::Timestamp ts1(2024, 6, 15, 14, 30, 45);
22275      if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
22276          ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
22277        pass = false;
22278        fail_msg = "Component constructor values incorrect";
22279      }
22280
22281      // With microseconds and nanoseconds
22282      numpy::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
22283      if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
22284        pass = false;
22285        fail_msg = "Microsecond/nanosecond values incorrect";
day_name (np_test_5_all.cpp:22826)
22816      // strftime
22817      std::string fmt = ts.strftime("%Y/%m/%d");
22818      if (fmt != "2024/06/15") { pass = false; fail_msg = "strftime format"; }
22819
22820      // ctime
22821      std::string ct = ts.ctime();
22822      if (ct.find("2024") == std::string::npos) { pass = false; fail_msg = "ctime should contain year"; }
22823
22824      // day_name
22825      std::string dayname = ts.day_name();
22826      if (dayname != "Saturday") { pass = false; fail_msg = "2024-06-15 is Saturday"; }
22827
22828      // month_name
22829      std::string monthname = ts.month_name();
22830      if (monthname != "June") { pass = false; fail_msg = "Month should be June"; }
22831
22832      if (!pass) {
22833        std::cout << "  [FAIL] : in np_test_timestamp_strings() : " << fail_msg;
22834        throw std::runtime_error("np_test_timestamp_strings failed: " + fail_msg);
22835      }
day_of_week (np_test_5_all.cpp:22639)
22629    void np_test_timestamp_derived() {
22630      std::cout << "========= timestamp: derived properties ==========================";
22631
22632      auto pass = true;
22633      std::string fail_msg;
22634
22635      // 2024-06-15 is a Saturday
22636      numpy::Timestamp ts(2024, 6, 15);
22637
22638      if (ts.dayofweek() != 5) { pass = false; fail_msg = "2024-06-15 should be Saturday (5)"; }
22639      if (ts.day_of_week() != 5) { pass = false; fail_msg = "day_of_week alias"; }
22640      if (ts.dayofyear() != 167) { pass = false; fail_msg = "2024-06-15 should be day 167"; }
22641      if (ts.day_of_year() != 167) { pass = false; fail_msg = "day_of_year alias"; }
22642      if (ts.quarter() != 2) { pass = false; fail_msg = "June is Q2"; }
22643      if (ts.days_in_month() != 30) { pass = false; fail_msg = "June has 30 days"; }
22644
22645      int week = ts.week();
22646      if (week < 1 || week > 53) { pass = false; fail_msg = "week should be 1-53"; }
22647
22648      if (!pass) {
22649        std::cout << "  [FAIL] : in np_test_timestamp_derived() : " << fail_msg;
day_of_year (np_test_5_all.cpp:22641)
22631      auto pass = true;
22632      std::string fail_msg;
22633
22634      // 2024-06-15 is a Saturday
22635      numpy::Timestamp ts(2024, 6, 15);
22636
22637      if (ts.dayofweek() != 5) { pass = false; fail_msg = "2024-06-15 should be Saturday (5)"; }
22638      if (ts.day_of_week() != 5) { pass = false; fail_msg = "day_of_week alias"; }
22639      if (ts.dayofyear() != 167) { pass = false; fail_msg = "2024-06-15 should be day 167"; }
22640      if (ts.day_of_year() != 167) { pass = false; fail_msg = "day_of_year alias"; }
22641      if (ts.quarter() != 2) { pass = false; fail_msg = "June is Q2"; }
22642      if (ts.days_in_month() != 30) { pass = false; fail_msg = "June has 30 days"; }
22643
22644      int week = ts.week();
22645      if (week < 1 || week > 53) { pass = false; fail_msg = "week should be 1-53"; }
22646
22647      if (!pass) {
22648        std::cout << "  [FAIL] : in np_test_timestamp_derived() : " << fail_msg;
22649        throw std::runtime_error("np_test_timestamp_derived failed: " + fail_msg);
22650      }
dayofweek (np_test_5_all.cpp:22638)
22628    void np_test_timestamp_derived() {
22629      std::cout << "========= timestamp: derived properties ==========================";
22630
22631      auto pass = true;
22632      std::string fail_msg;
22633
22634      // 2024-06-15 is a Saturday
22635      numpy::Timestamp ts(2024, 6, 15);
22636
22637      if (ts.dayofweek() != 5) { pass = false; fail_msg = "2024-06-15 should be Saturday (5)"; }
22638      if (ts.day_of_week() != 5) { pass = false; fail_msg = "day_of_week alias"; }
22639      if (ts.dayofyear() != 167) { pass = false; fail_msg = "2024-06-15 should be day 167"; }
22640      if (ts.day_of_year() != 167) { pass = false; fail_msg = "day_of_year alias"; }
22641      if (ts.quarter() != 2) { pass = false; fail_msg = "June is Q2"; }
22642      if (ts.days_in_month() != 30) { pass = false; fail_msg = "June has 30 days"; }
22643
22644      int week = ts.week();
22645      if (week < 1 || week > 53) { pass = false; fail_msg = "week should be 1-53"; }
22646
22647      if (!pass) {
dayofyear (np_test_5_all.cpp:22640)
22630      std::cout << "========= timestamp: derived properties ==========================";
22631
22632      auto pass = true;
22633      std::string fail_msg;
22634
22635      // 2024-06-15 is a Saturday
22636      numpy::Timestamp ts(2024, 6, 15);
22637
22638      if (ts.dayofweek() != 5) { pass = false; fail_msg = "2024-06-15 should be Saturday (5)"; }
22639      if (ts.day_of_week() != 5) { pass = false; fail_msg = "day_of_week alias"; }
22640      if (ts.dayofyear() != 167) { pass = false; fail_msg = "2024-06-15 should be day 167"; }
22641      if (ts.day_of_year() != 167) { pass = false; fail_msg = "day_of_year alias"; }
22642      if (ts.quarter() != 2) { pass = false; fail_msg = "June is Q2"; }
22643      if (ts.days_in_month() != 30) { pass = false; fail_msg = "June has 30 days"; }
22644
22645      int week = ts.week();
22646      if (week < 1 || week > 53) { pass = false; fail_msg = "week should be 1-53"; }
22647
22648      if (!pass) {
22649        std::cout << "  [FAIL] : in np_test_timestamp_derived() : " << fail_msg;
22650        throw std::runtime_error("np_test_timestamp_derived failed: " + fail_msg);
days_in_month (np_test_5_all.cpp:22643)
22633      std::string fail_msg;
22634
22635      // 2024-06-15 is a Saturday
22636      numpy::Timestamp ts(2024, 6, 15);
22637
22638      if (ts.dayofweek() != 5) { pass = false; fail_msg = "2024-06-15 should be Saturday (5)"; }
22639      if (ts.day_of_week() != 5) { pass = false; fail_msg = "day_of_week alias"; }
22640      if (ts.dayofyear() != 167) { pass = false; fail_msg = "2024-06-15 should be day 167"; }
22641      if (ts.day_of_year() != 167) { pass = false; fail_msg = "day_of_year alias"; }
22642      if (ts.quarter() != 2) { pass = false; fail_msg = "June is Q2"; }
22643      if (ts.days_in_month() != 30) { pass = false; fail_msg = "June has 30 days"; }
22644
22645      int week = ts.week();
22646      if (week < 1 || week > 53) { pass = false; fail_msg = "week should be 1-53"; }
22647
22648      if (!pass) {
22649        std::cout << "  [FAIL] : in np_test_timestamp_derived() : " << fail_msg;
22650        throw std::runtime_error("np_test_timestamp_derived failed: " + fail_msg);
22651      }
22652
22653      std::cout << " -> tests passed" << std::endl;
dst (np_test_5_all.cpp:23011)
23001      }
23002
23003      // utcoffset
23004      numpy::timedelta64 offset = localized.utcoffset();
23005      if (offset.isNaT()) {
23006        pass = false;
23007        fail_msg = "utcoffset should not be NaT";
23008      }
23009
23010      // dst
23011      numpy::timedelta64 dst_val = localized.dst();
23012      if (dst_val.isNaT()) {
23013        pass = false;
23014        fail_msg = "dst should not be NaT";
23015      }
23016
23017      if (!pass) {
23018        std::cout << "  [FAIL] : in np_test_timestamp_tz_methods() : " << fail_msg;
23019        throw std::runtime_error("np_test_timestamp_tz_methods failed: " + fail_msg);
23020      }
fold (np_test_5_all.cpp:22717)
22707      std::string fail_msg;
22708
22709      // Naive timestamp
22710      numpy::Timestamp naive(2024, 6, 15);
22711      if (!naive.tz().empty()) { pass = false; fail_msg = "Naive should have empty tz"; }
22712      if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; }
22713
22714      // UTC timestamp
22715      numpy::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC");
22716      if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; }
22717      if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; }
22718
22719      // Named timezone
22720      numpy::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York");
22721      if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; }
22722      std::string tzname = ny.tzname();
22723      if (tzname != "EDT" && tzname != "EST") { pass = false; fail_msg = "Summer should be EDT or EST"; }
22724
22725      if (!pass) {
22726        std::cout << "  [FAIL] : in np_test_timestamp_timezone() : " << fail_msg;
22727        throw std::runtime_error("np_test_timestamp_timezone failed: " + fail_msg);
fromisocalendar (np_test_5_all.cpp:22392)
22382      }
22383
22384      std::cout << " -> tests passed" << std::endl;
22385    }
22386
22387    // ============================================================================
22388    // STATIC FACTORY METHODS - Plan 11 (fromisocalendar, fromisoformat, strptime)
22389    // ============================================================================
22390
22391    void np_test_timestamp_fromisocalendar() {
22392      std::cout << "========= Timestamp::fromisocalendar() ===============";
22393
22394      // Test 1: Basic ISO calendar to date conversion
22395      // 2024, week 1, Monday (Jan 1, 2024 was Monday of week 1)
22396      numpy::Timestamp ts1 = numpy::Timestamp::fromisocalendar(2024, 1, 1);
22397      if (ts1.year() != 2024 || ts1.month() != 1 || ts1.day() != 1) {
22398        throw std::runtime_error("fromisocalendar failed: 2024-W01-1 should be 2024-01-01");
22399      }
22400
22401      // Test 2: 2020, week 1, Wednesday (Jan 1, 2020 was Wednesday)
22402      numpy::Timestamp ts2 = numpy::Timestamp::fromisocalendar(2020, 1, 3);
fromisoformat (np_test_5_all.cpp:22449)
22439        threw = true;
22440      }
22441      if (!threw) {
22442        throw std::runtime_error("fromisocalendar failed: should throw for weekday 8");
22443      }
22444
22445      std::cout << " -> tests passed" << std::endl;
22446    }
22447
22448    void np_test_timestamp_fromisoformat() {
22449      std::cout << "========= Timestamp::fromisoformat() ==================";
22450
22451      // Test 1: Date only
22452      numpy::Timestamp ts1 = numpy::Timestamp::fromisoformat("2024-03-15");
22453      if (ts1.year() != 2024 || ts1.month() != 3 || ts1.day() != 15) {
22454        throw std::runtime_error("fromisoformat failed: date only parsing");
22455      }
22456
22457      // Test 2: Date and time with T separator
22458      numpy::Timestamp ts2 = numpy::Timestamp::fromisoformat("2024-03-15T14:30:00");
22459      if (ts2.year() != 2024 || ts2.month() != 3 || ts2.day() != 15 ||
fromordinal (np_test_5_all.cpp:22357)
22347      }
22348
22349      // fromtimestamp - Unix epoch
22350      numpy::Timestamp epoch = numpy::Timestamp::fromtimestamp(0.0);
22351      if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) {
22352        pass = false;
22353        fail_msg = "fromtimestamp(0) should be epoch";
22354      }
22355
22356      // fromordinal
22357      numpy::Timestamp from_ord = numpy::Timestamp::fromordinal(738678);
22358      if (from_ord.isNaT()) {
22359        pass = false;
22360        fail_msg = "fromordinal should not return NaT";
22361      }
22362
22363      // combine
22364      numpy::Timestamp combined = numpy::Timestamp::combine({2024, 6, 15}, {12, 30, 45, 0});
22365      if (combined.year() != 2024 || combined.hour() != 12) {
22366        pass = false;
22367        fail_msg = "combine() values incorrect";
fromtimestamp (np_test_5_all.cpp:22350)
22340      }
22341
22342      // utcnow()
22343      numpy::Timestamp utcnow = numpy::Timestamp::utcnow();
22344      if (utcnow.isNaT() || utcnow.tz() != "UTC") {
22345        pass = false;
22346        fail_msg = "utcnow() should have UTC timezone";
22347      }
22348
22349      // fromtimestamp - Unix epoch
22350      numpy::Timestamp epoch = numpy::Timestamp::fromtimestamp(0.0);
22351      if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) {
22352        pass = false;
22353        fail_msg = "fromtimestamp(0) should be epoch";
22354      }
22355
22356      // fromordinal
22357      numpy::Timestamp from_ord = numpy::Timestamp::fromordinal(738678);
22358      if (from_ord.isNaT()) {
22359        pass = false;
22360        fail_msg = "fromordinal should not return NaT";
hour (np_test_5_all.cpp:22277)
22267      // Default constructor (NaT)
22268      numpy::Timestamp nat;
22269      if (!nat.isNaT()) {
22270        pass = false;
22271        fail_msg = "Default constructor should create NaT";
22272      }
22273
22274      // Component constructor
22275      numpy::Timestamp ts1(2024, 6, 15, 14, 30, 45);
22276      if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
22277          ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
22278        pass = false;
22279        fail_msg = "Component constructor values incorrect";
22280      }
22281
22282      // With microseconds and nanoseconds
22283      numpy::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
22284      if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
22285        pass = false;
22286        fail_msg = "Microsecond/nanosecond values incorrect";
22287      }
isNaT (np_test_1_all.cpp:6821)
6811    std::cout << " -> tests passed" << std::endl;
6812}
6813
6814// DateTime Functions (merged from np_test_datetime.cpp)
6815void testDatetime64CreationDateTime() {
6816    std::cout << "========= testDatetime64CreationDateTime =======================";
6817
6818    // Test default constructor
6819    datetime64 default_dt;
6820    if (!(default_dt.isNaT())) {
6821        std::string description = std::string("testDatetime64CreationDateTime():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(default_dt.isNaT())";
6822        std::cout << std::string("[FAIL] ") + description << std::endl;
6823        throw std::runtime_error(description);
6824    }
6825    // std::cout << "Default datetime64 is NaT: " << default_dt.toString() << std::endl;
6826
6827    // Test value constructor
6828    datetime64 epoch_day(0, DateTimeUnit::Day);
6829    // std::cout << "Epoch day: " << epoch_day.toString() << std::endl;
isoformat (np_test_5_all.cpp:21539)
21529        if (nat.toString() != "NaT") {
21530            std::cout << "[FAIL] np_test_timedelta_strings: toString(NaT) expected 'NaT', got '"
21531                      << nat.toString() << "'" << std::endl;
21532            errors++;
21533        }
21534    }
21535
21536    // isoformat
21537    {
21538        numpy::Timedelta td(1, 2, 30);
21539        std::string iso = td.isoformat();
21540        if (iso.find("P1D") == std::string::npos) {
21541            std::cout << "[FAIL] np_test_timedelta_strings: isoformat expected 'P1D...', got '"
21542                      << iso << "'" << std::endl;
21543            errors++;
21544        }
21545    }
21546
21547    // components_str
21548    {
21549        numpy::Timedelta td(1, 2, 30, 45, 100, 200, 300);
isoweekday (np_test_5_all.cpp:22859)
22849      std::string fail_msg;
22850
22851      numpy::Timestamp ts(2024, 6, 15);
22852
22853      // isocalendar
22854      auto [iso_year, iso_week, iso_day] = ts.isocalendar();
22855      if (iso_year != 2024) { pass = false; fail_msg = "ISO year should be 2024"; }
22856      if (iso_week < 1 || iso_week > 53) { pass = false; fail_msg = "ISO week range"; }
22857      if (iso_day < 1 || iso_day > 7) { pass = false; fail_msg = "ISO day range 1-7"; }
22858
22859      // isoweekday (1=Monday, 7=Sunday)
22860      int isowd = ts.isoweekday();
22861      if (isowd != 6) { pass = false; fail_msg = "2024-06-15 is Saturday = 6"; }
22862
22863      // weekday (0=Monday, 6=Sunday)
22864      int wd = ts.weekday();
22865      if (wd != 5) { pass = false; fail_msg = "2024-06-15 is Saturday = 5"; }
22866
22867      if (!pass) {
22868        std::cout << "  [FAIL] : in np_test_timestamp_calendar() : " << fail_msg;
22869        throw std::runtime_error("np_test_timestamp_calendar failed: " + fail_msg);
microsecond (np_test_5_all.cpp:22284)
22274      // Component constructor
22275      numpy::Timestamp ts1(2024, 6, 15, 14, 30, 45);
22276      if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
22277          ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
22278        pass = false;
22279        fail_msg = "Component constructor values incorrect";
22280      }
22281
22282      // With microseconds and nanoseconds
22283      numpy::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
22284      if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
22285        pass = false;
22286        fail_msg = "Microsecond/nanosecond values incorrect";
22287      }
22288
22289      // String constructor - ISO format
22290      numpy::Timestamp ts3("2024-06-15T14:30:45");
22291      if (ts3.year() != 2024 || ts3.month() != 6 || ts3.day() != 15) {
22292        pass = false;
22293        fail_msg = "String constructor parse failed";
22294      }
month (np_test_5_all.cpp:22276)
22266      // Default constructor (NaT)
22267      numpy::Timestamp nat;
22268      if (!nat.isNaT()) {
22269        pass = false;
22270        fail_msg = "Default constructor should create NaT";
22271      }
22272
22273      // Component constructor
22274      numpy::Timestamp ts1(2024, 6, 15, 14, 30, 45);
22275      if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
22276          ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
22277        pass = false;
22278        fail_msg = "Component constructor values incorrect";
22279      }
22280
22281      // With microseconds and nanoseconds
22282      numpy::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
22283      if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
22284        pass = false;
22285        fail_msg = "Microsecond/nanosecond values incorrect";
month_name (np_test_5_all.cpp:22830)
22820      // ctime
22821      std::string ct = ts.ctime();
22822      if (ct.find("2024") == std::string::npos) { pass = false; fail_msg = "ctime should contain year"; }
22823
22824      // day_name
22825      std::string dayname = ts.day_name();
22826      if (dayname != "Saturday") { pass = false; fail_msg = "2024-06-15 is Saturday"; }
22827
22828      // month_name
22829      std::string monthname = ts.month_name();
22830      if (monthname != "June") { pass = false; fail_msg = "Month should be June"; }
22831
22832      if (!pass) {
22833        std::cout << "  [FAIL] : in np_test_timestamp_strings() : " << fail_msg;
22834        throw std::runtime_error("np_test_timestamp_strings failed: " + fail_msg);
22835      }
22836
22837      std::cout << " -> tests passed" << std::endl;
22838    }
now (np_test_1_all.cpp:3611)
3601void test_broadcasting_performance() {
3602    std::cout << "========= test_broadcasting_performance =======================";
3603    // std::cout << "Testing broadcasting performance..." << std::endl;
3604
3605    // Create larger arrays for performance testing
3606    auto large_arr = NDArray<double>::createOnes({100, 100});
3607    auto broadcast_arr = NDArray<double>::createOnes({1, 100});
3608
3609    // Time the operation (basic timing)
3610    auto start = std::chrono::high_resolution_clock::now();
3611    auto result = large_arr.addArrays(broadcast_arr);
3612    auto end = std::chrono::high_resolution_clock::now();
3613
3614    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
3615    // std::cout << "Large array broadcasting took " << duration.count() << " microseconds" << std::endl;
3616
3617    // Verify result shape
3618    if (!((result.getShape() == std::vector<size_t>{100, 100}))) {
3619        std::string description = std::string("test_broadcasting_performance():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !((result.getShape() == std::vector<size_t>{100, 100}))";
3620        std::cout << std::string("[FAIL] ") + description << std::endl;
quarter (np_test_5_all.cpp:22642)
22632      auto pass = true;
22633      std::string fail_msg;
22634
22635      // 2024-06-15 is a Saturday
22636      numpy::Timestamp ts(2024, 6, 15);
22637
22638      if (ts.dayofweek() != 5) { pass = false; fail_msg = "2024-06-15 should be Saturday (5)"; }
22639      if (ts.day_of_week() != 5) { pass = false; fail_msg = "day_of_week alias"; }
22640      if (ts.dayofyear() != 167) { pass = false; fail_msg = "2024-06-15 should be day 167"; }
22641      if (ts.day_of_year() != 167) { pass = false; fail_msg = "day_of_year alias"; }
22642      if (ts.quarter() != 2) { pass = false; fail_msg = "June is Q2"; }
22643      if (ts.days_in_month() != 30) { pass = false; fail_msg = "June has 30 days"; }
22644
22645      int week = ts.week();
22646      if (week < 1 || week > 53) { pass = false; fail_msg = "week should be 1-53"; }
22647
22648      if (!pass) {
22649        std::cout << "  [FAIL] : in np_test_timestamp_derived() : " << fail_msg;
22650        throw std::runtime_error("np_test_timestamp_derived failed: " + fail_msg);
22651      }
replace (np_test_1_all.cpp:6717)
6707    std::vector<std::string> text = {"Hello world", "The world is big", "world peace"};
6708    auto arr = array<64>(text);
6709
6710    // std::cout << "Original text:" << std::endl;
6711    for (size_t i = 0; i < arr.size(); ++i) {
6712        // std::cout << "'" << arr[i] << "'";
6713    }
6714
6715    // Test replace
6716    auto replaced = replace(arr, "world", "universe");
6717    // std::cout << "After replacing 'world' with 'universe':" << std::endl;
6718    for (size_t i = 0; i < replaced.size(); ++i) {
6719        // std::cout << "'" << replaced[i] << "'";
6720    }
6721
6722    // Test replace with count limit
6723    std::vector<std::string> repeated_text = {"test test test", "more test cases", "test everything"};
6724    auto repeated_arr = array<64>(repeated_text);
6725    auto limited_replace = replace(repeated_arr, "test", "example", 1);
second (np_test_5_all.cpp:22277)
22267      // Default constructor (NaT)
22268      numpy::Timestamp nat;
22269      if (!nat.isNaT()) {
22270        pass = false;
22271        fail_msg = "Default constructor should create NaT";
22272      }
22273
22274      // Component constructor
22275      numpy::Timestamp ts1(2024, 6, 15, 14, 30, 45);
22276      if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
22277          ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
22278        pass = false;
22279        fail_msg = "Component constructor values incorrect";
22280      }
22281
22282      // With microseconds and nanoseconds
22283      numpy::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
22284      if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
22285        pass = false;
22286        fail_msg = "Microsecond/nanosecond values incorrect";
22287      }
strftime (np_test_5_all.cpp:22818)
22808      // isoformat
22809      std::string iso = ts.isoformat();
22810      if (iso.find("2024-06-15") == std::string::npos) { pass = false; fail_msg = "isoformat should contain date"; }
22811
22812      // isoformat with space separator
22813      std::string iso_space = ts.isoformat(' ');
22814      if (iso_space.find(" ") == std::string::npos) { pass = false; fail_msg = "isoformat with space separator"; }
22815
22816      // strftime
22817      std::string fmt = ts.strftime("%Y/%m/%d");
22818      if (fmt != "2024/06/15") { pass = false; fail_msg = "strftime format"; }
22819
22820      // ctime
22821      std::string ct = ts.ctime();
22822      if (ct.find("2024") == std::string::npos) { pass = false; fail_msg = "ctime should contain year"; }
22823
22824      // day_name
22825      std::string dayname = ts.day_name();
22826      if (dayname != "Saturday") { pass = false; fail_msg = "2024-06-15 is Saturday"; }
strptime (np_test_5_all.cpp:22519)
22509        threw = true;
22510      }
22511      if (!threw) {
22512        throw std::runtime_error("fromisoformat failed: should throw for too short string");
22513      }
22514
22515      std::cout << " -> tests passed" << std::endl;
22516    }
22517
22518    void np_test_timestamp_strptime() {
22519      std::cout << "========= Timestamp::strptime() =======================";
22520
22521      // Test 1: Basic date parsing
22522      numpy::Timestamp ts1 = numpy::Timestamp::strptime("2024-03-15", "%Y-%m-%d");
22523      if (ts1.year() != 2024 || ts1.month() != 3 || ts1.day() != 15) {
22524        throw std::runtime_error("strptime failed: basic date parsing");
22525      }
22526
22527      // Test 2: Date and time parsing
22528      numpy::Timestamp ts2 = numpy::Timestamp::strptime("2024-03-15 14:30:45", "%Y-%m-%d %H:%M:%S");
22529      if (ts2.year() != 2024 || ts2.month() != 3 || ts2.day() != 15 ||
timestamp (np_test_1_all.cpp:8336)
8326    uint file_size = 18446744073709551000ULL; // NumPy: np.uint
8327    longlong big_number = 9223372036854775807LL; // NumPy: np.longlong
8328    ulonglong huge_number = 18446744073709551615ULL; // NumPy: np.ulonglong
8329
8330    // std::cout << "  pixel_intensity (byte): " << static_cast<int>(pixel_intensity) << std::endl;
8331    // std::cout << "  rgb_value (ubyte): " << static_cast<int>(rgb_value) << std::endl;
8332    // std::cout << "  temperature (short_): " << temperature << std::endl;
8333    // std::cout << "  elevation (ushort): " << elevation << std::endl;
8334    // std::cout << "  count (intc): " << count << std::endl;
8335    // std::cout << "  population (uintc): " << population << std::endl;
8336    // std::cout << "  timestamp (int_): " << timestamp << std::endl;
8337    // std::cout << "  file_size (uint): " << file_size << std::endl;
8338    // std::cout << "  big_number (longlong): " << big_number << std::endl;
8339    // std::cout << "  huge_number (ulonglong): " << huge_number << std::endl;
8340
8341    // Test array creation with NumPy-style types
8342    auto numpy_style_array = NDArray<int_>::createZeros({3, 3});  // Like np.zeros((3,3), dtype=np.int_)
8343    // std::cout << "NumPy-style array creation:";
8344    //numpy_style_array.printArray();
8345
8346    std::cout << " -> tests passed" << std::endl;
toString (np_test_1_all.cpp:6826)
6816void testDatetime64CreationDateTime() {
6817    std::cout << "========= testDatetime64CreationDateTime =======================";
6818
6819    // Test default constructor
6820    datetime64 default_dt;
6821    if (!(default_dt.isNaT())) {
6822        std::string description = std::string("testDatetime64CreationDateTime():") + __FILE__ + ":" + std::to_string(__LINE__) + ": !(default_dt.isNaT())";
6823        std::cout << std::string("[FAIL] ") + description << std::endl;
6824        throw std::runtime_error(description);
6825    }
6826    // std::cout << "Default datetime64 is NaT: " << default_dt.toString() << std::endl;
6827
6828    // Test value constructor
6829    datetime64 epoch_day(0, DateTimeUnit::Day);
6830    // std::cout << "Epoch day: " << epoch_day.toString() << std::endl;
6831
6832    // Test string constructor
6833    datetime64 date_from_string("2024-01-15");
6834    // std::cout << "Date from string '2024-01-15': " << date_from_string.toString() << std::endl;
6835
6836    datetime64 datetime_from_string("2024-01-15T10:30:45");
today (np_test_1_all.cpp:6840)
6830    // std::cout << "Epoch day: " << epoch_day.toString() << std::endl;
6831
6832    // Test string constructor
6833    datetime64 date_from_string("2024-01-15");
6834    // std::cout << "Date from string '2024-01-15': " << date_from_string.toString() << std::endl;
6835
6836    datetime64 datetime_from_string("2024-01-15T10:30:45");
6837    // std::cout << "DateTime from string '2024-01-15T10:30:45': " << datetime_from_string.toString() << std::endl;
6838
6839    // Test static methods
6840    datetime64 today = datetime64::today();
6841    // std::cout << "Today: " << today.toString() << std::endl;
6842
6843    datetime64 now = datetime64::now();
6844    // std::cout << "Now: " << now.toString() << std::endl;
6845
6846        std::cout << " -> tests passed" << std::endl;
6847}
6848
6849void testTimedelta64CreationDateTime() {
6850    std::cout << "========= testTimedelta64CreationDateTime =======================";
toordinal (np_test_5_all.cpp:22782)
22772      if (dy != 2024) { pass = false; fail_msg = "date tuple year"; }
22773
22774      auto [th, tmi, ts2, tus] = ts.time();
22775      if (th != 12) { pass = false; fail_msg = "time tuple hour"; }
22776
22777      // Julian date
22778      double jd = ts.to_julian_date();
22779      if (jd < 2400000) { pass = false; fail_msg = "Julian date should be reasonable"; }
22780
22781      // Ordinal
22782      int ord = ts.toordinal();
22783      if (ord <= 0) { pass = false; fail_msg = "Ordinal should be positive"; }
22784
22785      if (!pass) {
22786        std::cout << "  [FAIL] : in np_test_timestamp_conversions() : " << fail_msg;
22787        throw std::runtime_error("np_test_timestamp_conversions failed: " + fail_msg);
22788      }
22789
22790      std::cout << " -> tests passed" << std::endl;
22791    }
tz (np_test_5_all.cpp:22305)
22295      // String with fractional seconds
22296      numpy::Timestamp ts4("2024-01-01T12:00:00.123456789");
22297      if (ts4.microsecond() != 123456 || ts4.nanosecond() != 789) {
22298        pass = false;
22299        fail_msg = "Fractional seconds parse failed";
22300      }
22301
22302      // String with Z timezone
22303      numpy::Timestamp ts5("2024-06-15T12:00:00Z");
22304      if (ts5.tz() != "UTC") {
22305        pass = false;
22306        fail_msg = "Z timezone should parse as UTC";
22307      }
22308
22309      if (!pass) {
22310        std::cout << "  [FAIL] : in np_test_timestamp_constructors() : " << fail_msg;
22311        throw std::runtime_error("np_test_timestamp_constructors failed: " + fail_msg);
22312      }
22313
22314      std::cout << " -> tests passed" << std::endl;
tz_convert (np_test_5_all.cpp:22990)
22980      // tz_localize
22981      numpy::Timestamp naive(2024, 6, 15, 12, 0, 0);
22982      numpy::Timestamp localized = naive.tz_localize("America/New_York");
22983      if (localized.tz() != "America/New_York") {
22984        pass = false;
22985        fail_msg = "tz_localize should set timezone";
22986      }
22987
22988      // tz_convert
22989      numpy::Timestamp converted = localized.tz_convert("Europe/London");
22990      if (converted.tz() != "Europe/London") {
22991        pass = false;
22992        fail_msg = "tz_convert should change timezone";
22993      }
22994
22995      // astimezone (alias)
22996      numpy::Timestamp ast = localized.astimezone("UTC");
22997      if (ast.tz() != "UTC") {
22998        pass = false;
22999        fail_msg = "astimezone should convert to UTC";
tz_localize (np_test_5_all.cpp:22983)
22973    // ============================================================================
22974
22975    void np_test_timestamp_tz_methods() {
22976      std::cout << "========= timestamp: timezone methods ============================";
22977
22978      auto pass = true;
22979      std::string fail_msg;
22980
22981      // tz_localize
22982      numpy::Timestamp naive(2024, 6, 15, 12, 0, 0);
22983      numpy::Timestamp localized = naive.tz_localize("America/New_York");
22984      if (localized.tz() != "America/New_York") {
22985        pass = false;
22986        fail_msg = "tz_localize should set timezone";
22987      }
22988
22989      // tz_convert
22990      numpy::Timestamp converted = localized.tz_convert("Europe/London");
22991      if (converted.tz() != "Europe/London") {
22992        pass = false;
22993        fail_msg = "tz_convert should change timezone";
tzinfo (np_test_5_all.cpp:22712)
22702    void np_test_timestamp_timezone() {
22703      std::cout << "========= timestamp: timezone properties =========================";
22704
22705      auto pass = true;
22706      std::string fail_msg;
22707
22708      // Naive timestamp
22709      numpy::Timestamp naive(2024, 6, 15);
22710      if (!naive.tz().empty()) { pass = false; fail_msg = "Naive should have empty tz"; }
22711      if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; }
22712
22713      // UTC timestamp
22714      numpy::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC");
22715      if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; }
22716      if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; }
22717
22718      // Named timezone
22719      numpy::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York");
22720      if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; }
22721      std::string tzname = ny.tzname();
tzname (np_test_5_all.cpp:22722)
22712      if (!naive.tzinfo().empty()) { pass = false; fail_msg = "Naive should have empty tzinfo"; }
22713
22714      // UTC timestamp
22715      numpy::Timestamp utc(2024, 6, 15, 12, 0, 0, 0, 0, "UTC");
22716      if (utc.tz() != "UTC") { pass = false; fail_msg = "Should have UTC timezone"; }
22717      if (utc.fold() != 0) { pass = false; fail_msg = "fold should be 0"; }
22718
22719      // Named timezone
22720      numpy::Timestamp ny(2024, 6, 15, 12, 0, 0, 0, 0, "America/New_York");
22721      if (ny.tz() != "America/New_York") { pass = false; fail_msg = "Should have NY timezone"; }
22722      std::string tzname = ny.tzname();
22723      if (tzname != "EDT" && tzname != "EST") { pass = false; fail_msg = "Summer should be EDT or EST"; }
22724
22725      if (!pass) {
22726        std::cout << "  [FAIL] : in np_test_timestamp_timezone() : " << fail_msg;
22727        throw std::runtime_error("np_test_timestamp_timezone failed: " + fail_msg);
22728      }
22729
22730      std::cout << " -> tests passed" << std::endl;
22731    }
utcfromtimestamp (np_test_5_all.cpp:23259)
23249      }
23250      if (pass && ts_from_nanos.month() != 6) {
23251        pass = false;
23252        fail_msg = "Timestamp(int64_t) month should be 6, got " + std::to_string(ts_from_nanos.month());
23253      }
23254      if (pass && ts_from_nanos.day() != 15) {
23255        pass = false;
23256        fail_msg = "Timestamp(int64_t) day should be 15, got " + std::to_string(ts_from_nanos.day());
23257      }
23258
23259      // Test 2: utcfromtimestamp(double ts) - creates UTC timestamp from POSIX timestamp
23260      // 1718454645.0 = 2024-06-15 12:30:45 UTC (verified with Python)
23261      double posix_ts = 1718454645.0;
23262      numpy::Timestamp utc_ts = numpy::Timestamp::utcfromtimestamp(posix_ts);
23263      if (pass && utc_ts.year() != 2024) { pass = false; fail_msg = "utcfromtimestamp year mismatch, got " + std::to_string(utc_ts.year()); }
23264      if (pass && utc_ts.month() != 6) { pass = false; fail_msg = "utcfromtimestamp month mismatch, got " + std::to_string(utc_ts.month()); }
23265      if (pass && utc_ts.day() != 15) { pass = false; fail_msg = "utcfromtimestamp day mismatch, got " + std::to_string(utc_ts.day()); }
23266      if (pass && utc_ts.hour() != 12) { pass = false; fail_msg = "utcfromtimestamp hour mismatch, got " + std::to_string(utc_ts.hour()); }
23267      if (pass && utc_ts.minute() != 30) { pass = false; fail_msg = "utcfromtimestamp minute mismatch, got " + std::to_string(utc_ts.minute()); }
23268      if (pass && utc_ts.second() != 45) { pass = false; fail_msg = "utcfromtimestamp second mismatch, got " + std::to_string(utc_ts.second()); }
23269      if (pass && utc_ts.tz() != "UTC") { pass = false; fail_msg = "utcfromtimestamp should have UTC timezone, got '" + utc_ts.tz() + "'"; }
utcnow (np_test_5_all.cpp:22342)
22332        fail_msg = "now() should not return NaT";
22333      }
22334
22335      // today()
22336      numpy::Timestamp today = numpy::Timestamp::today();
22337      if (today.hour() != 0 || today.minute() != 0 || today.second() != 0) {
22338        pass = false;
22339        fail_msg = "today() should be at midnight";
22340      }
22341
22342      // utcnow()
22343      numpy::Timestamp utcnow = numpy::Timestamp::utcnow();
22344      if (utcnow.isNaT() || utcnow.tz() != "UTC") {
22345        pass = false;
22346        fail_msg = "utcnow() should have UTC timezone";
22347      }
22348
22349      // fromtimestamp - Unix epoch
22350      numpy::Timestamp epoch = numpy::Timestamp::fromtimestamp(0.0);
22351      if (epoch.year() != 1970 || epoch.month() != 1 || epoch.day() != 1) {
22352        pass = false;
utcoffset (np_test_5_all.cpp:23004)
22994      }
22995
22996      // astimezone (alias)
22997      numpy::Timestamp ast = localized.astimezone("UTC");
22998      if (ast.tz() != "UTC") {
22999        pass = false;
23000        fail_msg = "astimezone should convert to UTC";
23001      }
23002
23003      // utcoffset
23004      numpy::timedelta64 offset = localized.utcoffset();
23005      if (offset.isNaT()) {
23006        pass = false;
23007        fail_msg = "utcoffset should not be NaT";
23008      }
23009
23010      // dst
23011      numpy::timedelta64 dst_val = localized.dst();
23012      if (dst_val.isNaT()) {
23013        pass = false;
23014        fail_msg = "dst should not be NaT";
value (np_test_1_all.cpp:7786)
7776}
7777
7778void testFloat16PrecisionFloat16() {
7779    std::cout << "========= testFloat16PrecisionFloat16 =======================";
7780
7781    // Test precision limits
7782    float16 small_val(0.0001f);
7783    float16 large_val(30000.0f);
7784    float16 very_small(1e-8f);  // This might underflow to zero
7785
7786    // std::cout << "Small value (0.0001): " << small_val << std::endl;
7787    // std::cout << "Large value (30000): " << large_val << std::endl;
7788    // std::cout << "Very small value (1e-8): " << very_small << std::endl;
7789
7790    // Test conversion accuracy
7791    float original = 1.234f;
7792    float16 converted(original);
7793    float back_converted = static_cast<float>(converted);
7794
7795    // std::cout << "Original float: " << std::setprecision(10) << original << std::endl;
7796    // std::cout << "Float16 version: " << converted << std::endl;
week (np_test_1_all.cpp:27347)
27337      std::cout << "========= busday_offset: forward offset =======================";
27338
27339      // Start on Monday, offset by 5 business days -> should be next Monday
27340      NDArray<datetime64> dates({ 1 });
27341      NDArray<int64_t> offsets({ 1 });
27342      dates.setElementAt({ 0 }, datetime64(19723, DateTimeUnit::Day)); // 2024-01-01 (Monday)
27343      offsets.setElementAt({ 0 }, int64_t(5));
27344
27345      auto result = busday_offset(dates, offsets);
27346
27347      // Expected: Monday + 5 business days = Monday next week (skipping weekend)
27348      datetime64 expected(19730, DateTimeUnit::Day); // 2024-01-08 (Monday)
27349
27350      if (result.getElementAt({ 0 }) != expected) {
27351        std::cout << "  [FAIL] : in test_busday_offset_forward() : incorrect offset result";
27352        throw std::runtime_error("busday_offset forward test failed");
27353      }
27354
27355      std::cout << " -> tests passed" << std::endl;
27356    }
weekday (np_test_5_all.cpp:22863)
22853      // isocalendar
22854      auto [iso_year, iso_week, iso_day] = ts.isocalendar();
22855      if (iso_year != 2024) { pass = false; fail_msg = "ISO year should be 2024"; }
22856      if (iso_week < 1 || iso_week > 53) { pass = false; fail_msg = "ISO week range"; }
22857      if (iso_day < 1 || iso_day > 7) { pass = false; fail_msg = "ISO day range 1-7"; }
22858
22859      // isoweekday (1=Monday, 7=Sunday)
22860      int isowd = ts.isoweekday();
22861      if (isowd != 6) { pass = false; fail_msg = "2024-06-15 is Saturday = 6"; }
22862
22863      // weekday (0=Monday, 6=Sunday)
22864      int wd = ts.weekday();
22865      if (wd != 5) { pass = false; fail_msg = "2024-06-15 is Saturday = 5"; }
22866
22867      if (!pass) {
22868        std::cout << "  [FAIL] : in np_test_timestamp_calendar() : " << fail_msg;
22869        throw std::runtime_error("np_test_timestamp_calendar failed: " + fail_msg);
22870      }
22871
22872      std::cout << " -> tests passed" << std::endl;
22873    }
year (np_test_5_all.cpp:22276)
22266      // Default constructor (NaT)
22267      numpy::Timestamp nat;
22268      if (!nat.isNaT()) {
22269        pass = false;
22270        fail_msg = "Default constructor should create NaT";
22271      }
22272
22273      // Component constructor
22274      numpy::Timestamp ts1(2024, 6, 15, 14, 30, 45);
22275      if (ts1.year() != 2024 || ts1.month() != 6 || ts1.day() != 15 ||
22276          ts1.hour() != 14 || ts1.minute() != 30 || ts1.second() != 45) {
22277        pass = false;
22278        fail_msg = "Component constructor values incorrect";
22279      }
22280
22281      // With microseconds and nanoseconds
22282      numpy::Timestamp ts2(2024, 1, 1, 12, 0, 0, 123456, 789);
22283      if (ts2.microsecond() != 123456 || ts2.nanosecond() != 789) {
22284        pass = false;
22285        fail_msg = "Microsecond/nanosecond values incorrect";