* Applies a single business day offset. See the function * business_day_offset for the meaning of all the parameters. * * Returns 0 on success, -1 on failure. */
| 269 | * Returns 0 on success, -1 on failure. |
| 270 | */ |
| 271 | static int |
| 272 | apply_business_day_offset(npy_datetime date, npy_int64 offset, |
| 273 | npy_datetime *out, |
| 274 | NPY_BUSDAY_ROLL roll, |
| 275 | npy_bool *weekmask, int busdays_in_weekmask, |
| 276 | npy_datetime *holidays_begin, npy_datetime *holidays_end) |
| 277 | { |
| 278 | int day_of_week = 0; |
| 279 | npy_datetime *holidays_temp; |
| 280 | |
| 281 | /* Roll the date to a business day */ |
| 282 | if (apply_business_day_roll(date, &date, &day_of_week, |
| 283 | roll, |
| 284 | weekmask, |
| 285 | holidays_begin, holidays_end) < 0) { |
| 286 | return -1; |
| 287 | } |
| 288 | |
| 289 | /* If we get a NaT, just return it */ |
| 290 | if (date == NPY_DATETIME_NAT) { |
| 291 | *out = NPY_DATETIME_NAT; |
| 292 | return 0; |
| 293 | } |
| 294 | |
| 295 | /* Now we're on a valid business day */ |
| 296 | if (offset > 0) { |
| 297 | /* Remove any earlier holidays */ |
| 298 | holidays_begin = find_earliest_holiday_on_or_after(date, |
| 299 | holidays_begin, holidays_end); |
| 300 | |
| 301 | /* Jump by as many weeks as we can */ |
| 302 | date += (offset / busdays_in_weekmask) * 7; |
| 303 | offset = offset % busdays_in_weekmask; |
| 304 | |
| 305 | /* Adjust based on the number of holidays we crossed */ |
| 306 | holidays_temp = find_earliest_holiday_after(date, |
| 307 | holidays_begin, holidays_end); |
| 308 | offset += holidays_temp - holidays_begin; |
| 309 | holidays_begin = holidays_temp; |
| 310 | |
| 311 | /* Step until we use up the rest of the offset */ |
| 312 | while (offset > 0) { |
| 313 | ++date; |
| 314 | if (++day_of_week == 7) { |
| 315 | day_of_week = 0; |
| 316 | } |
| 317 | if (weekmask[day_of_week] && !is_holiday(date, |
| 318 | holidays_begin, holidays_end)) { |
| 319 | offset--; |
| 320 | } |
| 321 | } |
| 322 | } |
| 323 | else if (offset < 0) { |
| 324 | /* Remove any later holidays */ |
| 325 | holidays_end = find_earliest_holiday_after(date, |
| 326 | holidays_begin, holidays_end); |
| 327 | |
| 328 | /* Jump by as many weeks as we can */ |
no test coverage detected