* Converts a datetime based on the given metadata into a datetimestruct */
| 446 | * Converts a datetime based on the given metadata into a datetimestruct |
| 447 | */ |
| 448 | NPY_NO_EXPORT int |
| 449 | convert_datetime_to_datetimestruct(PyArray_DatetimeMetaData *meta, |
| 450 | npy_datetime dt, |
| 451 | npy_datetimestruct *out) |
| 452 | { |
| 453 | npy_int64 days; |
| 454 | |
| 455 | /* Initialize the output to all zeros */ |
| 456 | memset(out, 0, sizeof(npy_datetimestruct)); |
| 457 | out->year = 1970; |
| 458 | out->month = 1; |
| 459 | out->day = 1; |
| 460 | |
| 461 | /* NaT is signaled in the year */ |
| 462 | if (dt == NPY_DATETIME_NAT) { |
| 463 | out->year = NPY_DATETIME_NAT; |
| 464 | return 0; |
| 465 | } |
| 466 | |
| 467 | /* Datetimes can't be in generic units */ |
| 468 | if (meta->base == NPY_FR_GENERIC) { |
| 469 | PyErr_SetString(PyExc_ValueError, |
| 470 | "Cannot convert a NumPy datetime value other than NaT " |
| 471 | "with generic units"); |
| 472 | return -1; |
| 473 | } |
| 474 | |
| 475 | /* TODO: Change to a mechanism that avoids the potential overflow */ |
| 476 | dt *= meta->num; |
| 477 | |
| 478 | /* |
| 479 | * Note that care must be taken with the / and % operators |
| 480 | * for negative values. |
| 481 | */ |
| 482 | switch (meta->base) { |
| 483 | case NPY_FR_Y: |
| 484 | out->year = 1970 + dt; |
| 485 | break; |
| 486 | |
| 487 | case NPY_FR_M: |
| 488 | out->year = 1970 + extract_unit_64(&dt, 12); |
| 489 | out->month = dt + 1; |
| 490 | break; |
| 491 | |
| 492 | case NPY_FR_W: |
| 493 | /* A week is 7 days */ |
| 494 | set_datetimestruct_days(dt * 7, out); |
| 495 | break; |
| 496 | |
| 497 | case NPY_FR_D: |
| 498 | set_datetimestruct_days(dt, out); |
| 499 | break; |
| 500 | |
| 501 | case NPY_FR_h: |
| 502 | days = extract_unit_64(&dt, 24LL); |
| 503 | set_datetimestruct_days(days, out); |
| 504 | out->hour = (int)dt; |
| 505 | break; |
no test coverage detected