* Applies the given offsets in business days to the dates provided. * This is the low-level function which requires already cleaned input * data. * * dates: An array of dates with 'datetime64[D]' data type. * offsets: An array safely convertible into type int64. * out: Either NULL, or an array with 'datetime64[D]' data type * in which to place the resulting dates. * r
| 458 | * otherwise. |
| 459 | */ |
| 460 | NPY_NO_EXPORT PyArrayObject * |
| 461 | business_day_offset(PyArrayObject *dates, PyArrayObject *offsets, |
| 462 | PyArrayObject *out, |
| 463 | NPY_BUSDAY_ROLL roll, |
| 464 | npy_bool *weekmask, int busdays_in_weekmask, |
| 465 | npy_datetime *holidays_begin, npy_datetime *holidays_end) |
| 466 | { |
| 467 | PyArray_DatetimeMetaData temp_meta; |
| 468 | PyArray_Descr *dtypes[3] = {NULL, NULL, NULL}; |
| 469 | |
| 470 | NpyIter *iter = NULL; |
| 471 | PyArrayObject *op[3] = {NULL, NULL, NULL}; |
| 472 | npy_uint32 op_flags[3], flags; |
| 473 | |
| 474 | PyArrayObject *ret = NULL; |
| 475 | |
| 476 | if (busdays_in_weekmask == 0) { |
| 477 | PyErr_SetString(PyExc_ValueError, |
| 478 | "the business day weekmask must have at least one " |
| 479 | "valid business day"); |
| 480 | return NULL; |
| 481 | } |
| 482 | |
| 483 | /* First create the data types for dates and offsets */ |
| 484 | temp_meta.base = NPY_FR_D; |
| 485 | temp_meta.num = 1; |
| 486 | dtypes[0] = create_datetime_dtype(NPY_DATETIME, &temp_meta); |
| 487 | if (dtypes[0] == NULL) { |
| 488 | goto fail; |
| 489 | } |
| 490 | dtypes[1] = PyArray_DescrFromType(NPY_INT64); |
| 491 | if (dtypes[1] == NULL) { |
| 492 | goto fail; |
| 493 | } |
| 494 | dtypes[2] = dtypes[0]; |
| 495 | Py_INCREF(dtypes[2]); |
| 496 | |
| 497 | /* Set up the iterator parameters */ |
| 498 | flags = NPY_ITER_EXTERNAL_LOOP| |
| 499 | NPY_ITER_BUFFERED| |
| 500 | NPY_ITER_ZEROSIZE_OK; |
| 501 | op[0] = dates; |
| 502 | op_flags[0] = NPY_ITER_READONLY | NPY_ITER_ALIGNED; |
| 503 | op[1] = offsets; |
| 504 | op_flags[1] = NPY_ITER_READONLY | NPY_ITER_ALIGNED; |
| 505 | op[2] = out; |
| 506 | op_flags[2] = NPY_ITER_WRITEONLY | NPY_ITER_ALLOCATE | NPY_ITER_ALIGNED; |
| 507 | |
| 508 | /* Allocate the iterator */ |
| 509 | iter = NpyIter_MultiNew(3, op, flags, NPY_KEEPORDER, NPY_SAFE_CASTING, |
| 510 | op_flags, dtypes); |
| 511 | if (iter == NULL) { |
| 512 | goto fail; |
| 513 | } |
| 514 | |
| 515 | /* Loop over all elements */ |
| 516 | if (NpyIter_GetIterSize(iter) > 0) { |
| 517 | NpyIter_IterNextFunc *iternext; |
no test coverage detected