Transform numbers to np.timedelta64.
(
flat_num: np.ndarray,
time_unit: NPDatetimeUnitOptions,
ref_unit: PDDatetimeUnitOptions,
datatype: str,
target_unit: PDDatetimeUnitOptions | None = None,
)
| 614 | |
| 615 | |
| 616 | def _numbers_to_timedelta( |
| 617 | flat_num: np.ndarray, |
| 618 | time_unit: NPDatetimeUnitOptions, |
| 619 | ref_unit: PDDatetimeUnitOptions, |
| 620 | datatype: str, |
| 621 | target_unit: PDDatetimeUnitOptions | None = None, |
| 622 | ) -> np.ndarray: |
| 623 | """Transform numbers to np.timedelta64.""" |
| 624 | # keep NaT/nan mask |
| 625 | if flat_num.dtype.kind == "f": |
| 626 | nan = np.asarray(np.isnan(flat_num)) |
| 627 | elif flat_num.dtype.kind == "i": |
| 628 | nan = np.asarray(flat_num == np.iinfo(np.int64).min) |
| 629 | elif flat_num.dtype.kind == "u": |
| 630 | nan = np.broadcast_to(np.asarray(False), flat_num.shape) |
| 631 | |
| 632 | # in case we need to change the unit, we fix the numbers here |
| 633 | # this should be safe, as errors would have been raised above |
| 634 | ns_time_unit = _NS_PER_TIME_DELTA[time_unit] |
| 635 | ns_ref_date_unit = _NS_PER_TIME_DELTA[ref_unit] |
| 636 | if ns_time_unit > ns_ref_date_unit: |
| 637 | flat_num = np.asarray(flat_num * np.int64(ns_time_unit / ns_ref_date_unit)) |
| 638 | time_unit = ref_unit |
| 639 | |
| 640 | # estimate fitting resolution for floating point values |
| 641 | # this iterates until all floats are fractionless or time_unit == "ns" |
| 642 | if flat_num.dtype.kind == "f" and time_unit != "ns": |
| 643 | flat_num, new_time_unit = _check_higher_resolution( |
| 644 | flat_num, cast(PDDatetimeUnitOptions, time_unit) |
| 645 | ) |
| 646 | if time_unit != new_time_unit: |
| 647 | if target_unit is None or np.timedelta64(1, target_unit) > np.timedelta64( |
| 648 | 1, new_time_unit |
| 649 | ): |
| 650 | if datatype == "datetimes": |
| 651 | kwarg = "decode_times" |
| 652 | coder = "CFDatetimeCoder" |
| 653 | else: |
| 654 | kwarg = "decode_timedelta" |
| 655 | coder = "CFTimedeltaCoder" |
| 656 | formatted_kwarg = f"{kwarg}={coder}(time_unit={new_time_unit!r})" |
| 657 | message = ( |
| 658 | f"Can't decode floating point {datatype} to {time_unit!r} " |
| 659 | f"without precision loss; decoding to {new_time_unit!r} " |
| 660 | f"instead. To silence this warning pass {formatted_kwarg} " |
| 661 | f"to your opening function." |
| 662 | ) |
| 663 | emit_user_level_warning(message, SerializationWarning) |
| 664 | time_unit = new_time_unit |
| 665 | |
| 666 | # Cast input ordinals to integers and properly handle NaN/NaT |
| 667 | # to prevent casting NaN to int |
| 668 | with warnings.catch_warnings(): |
| 669 | warnings.simplefilter("ignore", RuntimeWarning) |
| 670 | flat_num = flat_num.astype(np.int64) |
| 671 | if nan.any(): |
| 672 | flat_num[nan] = np.iinfo(np.int64).min |
| 673 |
no test coverage detected
searching dependent graphs…