예제 #1
0
    def test_init(
        self,
        input_vals: Union[type, tuple[type, str]],
        set_time_ref: bool,
        scl: bool,
        arr: bool,
    ):
        """Test the `__init__` method of the time class.

        Parameters
        ----------
        input_vals :
            Either a compatible time type or a tuple of two values. The tuple is needed
            in case the tested time type can either represent relative time values as
            well as absolute ones. In this case, the first value is the type. The
            second value is a string specifying if the type represents absolute
            ("datetime") or relative ("timedelta") values.
        set_time_ref :
            If `True`, a reference time will be passed to the `__init__` method
        scl :
            If `True`, the data of the passed type consists of a single value.
        arr :
            If `True`, the data of the passed type is an array

        """
        input_type, is_timedelta = self._parse_time_type_test_input(input_vals)

        # skip matrix cases that do not work --------------------
        if arr and input_type in [Timedelta, Timestamp]:
            return
        if not arr and input_type in [DTI, TDI]:
            return

        # create input values -----------------------------------
        delta_val = [1, 2, 3]
        abs_val = [f"2000-01-01 16:00:0{v}" for v in delta_val]

        time = _initialize_time_type(input_type, delta_val, abs_val,
                                     is_timedelta, arr, scl)
        time_ref = "2000-01-01 15:00:00" if set_time_ref else None

        # create `Time` instance --------------------------------
        time_class_instance = Time(time, time_ref)

        # check results -----------------------------------------
        exp = self._get_init_exp_values(is_timedelta, time_ref, scl, delta_val,
                                        abs_val)

        assert time_class_instance.is_absolute == exp["is_absolute"]
        assert time_class_instance.reference_time == exp["time_ref"]
        assert np.all(time_class_instance.as_timedelta() == exp["timedelta"])
        if exp["is_absolute"]:
            assert np.all(time_class_instance.as_datetime() == exp["datetime"])
        else:
            with pytest.raises(TypeError):
                time_class_instance.as_datetime()
예제 #2
0
    def test_sub(
        self,
        other_type,
        other_on_rhs: bool,
        unit: str,
        time_class_is_array: bool,
        time_class_is_timedelta: bool,
        other_is_array: bool,
    ):
        """Test the `__sub__` method of the `Time` class.

        Parameters
        ----------
        other_type :
            The type of the other object
        other_on_rhs :
            If `True`, the other type is on the rhs of the + sign and on the lhs
            otherwise
        unit :
            The time unit to use
        time_class_is_array :
            If `True`, the `Time` instance contains 3 time values and 1 otherwise
        time_class_is_timedelta :
            If `True`, the `Time` instance represents a time delta and a datetime
            otherwise
        other_is_array :
            If `True`, the other time object contains 3 time values and 1 otherwise

        """
        other_type, other_is_timedelta = self._parse_time_type_test_input(
            other_type)
        if other_on_rhs:
            lhs_is_array = time_class_is_array
            lhs_is_timedelta = time_class_is_timedelta
            rhs_is_array = other_is_array
            rhs_is_timedelta = other_is_timedelta
        else:
            lhs_is_array = other_is_array
            lhs_is_timedelta = other_is_timedelta
            rhs_is_array = time_class_is_array
            rhs_is_timedelta = time_class_is_timedelta

        # skip array cases where the type does not support arrays or scalars
        if other_type in [Timedelta, Timestamp] and other_is_array:
            return
        if not other_is_array and other_type in [DTI, TDI]:
            return

        # skip __rsub__ cases where we got conflicts with the other types' __sub__
        if not other_on_rhs and other_type in (
                Q_,
                np.ndarray,
                np.timedelta64,
                np.datetime64,
                DTI,
                TDI,
        ):
            return

        # skip cases where an absolute time is on the rhs, since pandas does
        # not support this case (and it does not make sense)
        if lhs_is_timedelta and not rhs_is_timedelta:
            return

        # skip cases where the lhs is a scalar and the rhs is an array because it will
        # always involve non monotonically increasing array values, which is forbidden.
        if rhs_is_array and not lhs_is_array:
            return

        # test values
        vals_lhs = [3, 5, 9] if lhs_is_array else [3]
        vals_rhs = [1, 2, 3] if rhs_is_array else [1]

        # setup rhs
        other_val = vals_rhs if other_on_rhs else vals_lhs
        if unit == "s":
            abs_val = [f"2000-01-01 10:00:0{v}" for v in other_val]
        else:
            abs_val = [f"2000-01-01 1{v}:00:00" for v in other_val]
        other = _initialize_time_type(
            other_type,
            other_val,
            abs_val,
            other_is_timedelta,
            other_is_array,
            not other_is_array,
            unit,
        )

        # setup lhs
        time_class_values = vals_lhs if other_on_rhs else vals_rhs
        time_class_time_ref = None if time_class_is_timedelta else "2000-01-01 11:00:00"
        time_class = Time(Q_(time_class_values, unit), time_class_time_ref)

        # setup expected values
        sub = vals_rhs if other_is_array else vals_rhs[0]
        exp_val = np.array(vals_lhs) - sub
        if not other_is_timedelta:
            if time_class_is_timedelta:
                exp_val -= time_class_values[0] + exp_val[0]
            else:
                d = self._date_diff(time_class_time_ref, abs_val[0],
                                    unit) + vals_rhs[0]
                exp_val += d if other_on_rhs else (d + exp_val[0]) * -1

        exp_time_ref = None
        if not other_is_timedelta and time_class_is_timedelta:
            exp_time_ref = abs_val[0]
        elif other_is_timedelta and not time_class_is_timedelta:
            exp_time_ref = time_class_time_ref
        exp = Time(Q_(exp_val, unit), exp_time_ref)

        # calculate and evaluate result
        res = time_class - other if other_on_rhs else other - time_class

        assert res.reference_time == exp.reference_time
        assert np.all(res.as_timedelta() == exp.as_timedelta())
        assert np.all(res == exp)
예제 #3
0
    def test_add_datetime(
        other_type,
        other_on_rhs: bool,
        time_class_is_array: bool,
        other_is_array: bool,
    ):
        """Test the `__add__` method if the `Time` class represents a datetime.

        Parameters
        ----------
        other_type :
            The type of the other object
        other_on_rhs :
            If `True`, the other type is on the rhs of the + sign and on the lhs
            otherwise
        time_class_is_array :
            If `True`, the `Time` instance contains 3 time values and 1 otherwise
        other_is_array :
            If `True`, the other time object contains 3 time values and 1 otherwise

        """
        # skip array cases where the type does not support arrays
        if other_type in [Timedelta, Timestamp] and other_is_array:
            return
        if not other_is_array and other_type in [DTI, TDI]:
            return

        # skip __radd__ cases where we got conflicts with the other types' __add__
        if not other_on_rhs and other_type in (Q_, np.ndarray, np.timedelta64,
                                               TDI):
            return

        # setup rhs
        delta_val = [4, 6, 8]

        other = _initialize_time_type(
            other_type,
            delta_val,
            None,
            True,
            other_is_array,
            not other_is_array,
            "s",
        )

        # setup lhs
        time_class_values = [1, 2, 3] if time_class_is_array else [1]
        time_class = Time(Q_(time_class_values, "s"), "2000-01-01 10:00:00")

        # setup expected values
        add = delta_val if other_is_array else delta_val[0]
        exp_val = np.array(time_class_values) + add

        exp_time_ref = time_class.reference_time
        exp = Time(Q_(exp_val, "s"), exp_time_ref)

        # calculate and evaluate result
        res = time_class + other if other_on_rhs else other + time_class

        assert res.reference_time == exp.reference_time
        assert np.all(res.as_timedelta() == exp.as_timedelta())
        assert np.all(res == exp)
예제 #4
0
    def test_add_timedelta(
        self,
        other_type,
        other_on_rhs: bool,
        unit: str,
        time_class_is_array: bool,
        other_is_array: bool,
    ):
        """Test the `__add__` method if the `Time` class represents a time delta.

        Parameters
        ----------
        other_type :
            The type of the other object
        other_on_rhs :
            If `True`, the other type is on the rhs of the + sign and on the lhs
            otherwise
        unit :
            The time unit to use
        time_class_is_array :
            If `True`, the `Time` instance contains 3 time values and 1 otherwise
        other_is_array :
            If `True`, the other time object contains 3 time values and 1 otherwise

        """
        other_type, is_timedelta = self._parse_time_type_test_input(other_type)

        # skip array cases where the type does not support arrays
        if other_type in [Timedelta, Timestamp] and other_is_array:
            return
        if not other_is_array and other_type in [DTI, TDI]:
            return

        # skip __radd__ cases where we got conflicts with the other types' __add__
        if not other_on_rhs and other_type in (
                Q_,
                np.ndarray,
                np.timedelta64,
                np.datetime64,
                DTI,
                TDI,
        ):
            return

        # setup rhs
        delta_val = [4, 6, 8]
        if unit == "s":
            abs_val = [f"2000-01-01 10:00:0{v}" for v in delta_val]
        else:
            abs_val = [f"2000-01-01 1{v}:00:00" for v in delta_val]
        other = _initialize_time_type(
            other_type,
            delta_val,
            abs_val,
            is_timedelta,
            other_is_array,
            not other_is_array,
            unit,
        )

        # setup lhs
        time_class_values = [1, 2, 3] if time_class_is_array else [1]
        time_class = Time(Q_(time_class_values, unit))

        # setup expected values
        add = delta_val if other_is_array else delta_val[0]
        exp_val = np.array(time_class_values) + add
        exp_val += 0 if is_timedelta else time_class_values[0] - exp_val[0]

        exp_time_ref = None if is_timedelta else abs_val[0]
        exp = Time(Q_(exp_val, unit), exp_time_ref)

        # calculate and evaluate result
        res = time_class + other if other_on_rhs else other + time_class

        assert res.reference_time == exp.reference_time
        assert np.all(res.as_timedelta() == exp.as_timedelta())
        assert np.all(res == exp)