class TestToEquispacedTimeSeries:
    @given(
        series_with_period_index(),
        st.datetimes(),
        available_freqs(),
        st.text(),
    )
    def test_with_resample_false(
        self,
        series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
        output_name: str,
    ):
        time_series_preparation = TimeSeriesPreparation(
            start=start,
            freq=freq,
            resample_if_not_equispaced=False,
            output_name=output_name,
        )
        computed_series = time_series_preparation._to_equispaced_time_series(
            series)
        assert_series_equal(computed_series, series)

    @given(series_with_period_index(), st.datetimes(), available_freqs(),
           st.text())
    def test_with_resample_true(
        self,
        series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
        output_name: str,
    ):
        time_series_preparation = TimeSeriesPreparation(
            start=start,
            freq=freq,
            resample_if_not_equispaced=True,
            output_name=output_name,
        )
        with pytest.raises(NotImplementedError):
            time_series_preparation._to_equispaced_time_series(series)
class TestConstructor:
    @given(st.datetimes(), available_freqs(), st.booleans(), st.text())
    def test_constructor_does_not_fail(
        self,
        start: pd.datetime,
        freq: pd.Timedelta,
        resample_if_not_equispaced: bool,
        output_name: str,
    ):
        TimeSeriesPreparation(
            start=start,
            freq=freq,
            resample_if_not_equispaced=resample_if_not_equispaced,
            output_name=output_name,
        )

    @given(st.datetimes(), available_freqs(), st.booleans(), st.text())
    def test_constructor_initializes_parameters(
        self,
        start: pd.datetime,
        freq: pd.Timedelta,
        resample_if_not_equispaced: bool,
        output_name: str,
    ):
        time_series_preparation = TimeSeriesPreparation(
            start=start,
            freq=freq,
            resample_if_not_equispaced=resample_if_not_equispaced,
            output_name=output_name,
        )

        assert time_series_preparation.start == start
        assert time_series_preparation.end is None
        assert time_series_preparation.freq == freq
        assert (time_series_preparation.resample_if_not_equispaced ==
                resample_if_not_equispaced)
        assert time_series_preparation.output_name == output_name
class TestGeneric:
    @given(available_freqs())
    def test_available_freqs_is_timedelta(self, frequency):
        assert isinstance(frequency, pd.Timedelta)

    @given(positive_bounded_integers(100000))
    def test_positive_bounded_integers_is_positive(self, integer):
        assert integer >= 0

    @given(pair_of_ordered_timedeltas())
    def test_pair_of_ordered_timedeltas_is_ordered(self, pair):
        assert pair[0] < pair[1]

    @given(pair_of_ordered_dates())
    def test_pair_of_ordered_dates_is_ordered(self, pair):
        assert pair[0] < pair[1]

    @given(samples_from(NON_UNIFORM_FREQS))
    def test_freq_to_timedelta(self, freq: str):
        with pytest.raises(ValueError):
            freq_to_timedelta(freq, approximate_if_non_uniform=False)
class TestToTimeIndexSeries:
    @given(st.lists(st.floats()), st.datetimes(), available_freqs())
    def test_list_as_input(
        self,
        input_list: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
    ):
        time_series_preparation = TimeSeriesPreparation(start=start, freq=freq)
        computed_time_series = time_series_preparation._to_time_index_series(
            input_list)
        expected_time_series = pandas_series_with_period_index(input_list,
                                                               start,
                                                               freq=freq)
        assert_series_equal(computed_time_series, expected_time_series)

    @given(
        arrays(shape=st.integers(0, 1000), dtype=float),
        st.datetimes(),
        available_freqs(),
    )
    def test_array_as_input(
        self,
        input_array: np.ndarray,
        start: pd.datetime,
        freq: pd.Timedelta,
    ):
        time_series_preparation = TimeSeriesPreparation(start=start, freq=freq)
        computed_time_series = time_series_preparation._to_time_index_series(
            input_array)
        expected_time_series = pandas_series_with_period_index(input_array,
                                                               start,
                                                               freq=freq)
        assert_series_equal(computed_time_series, expected_time_series)

    @given(series_with_period_index(), st.datetimes(), available_freqs())
    def test_period_index_series_unchanged(
        self,
        period_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
    ):
        time_series_preparation = TimeSeriesPreparation(start=start, freq=freq)
        computed_time_series = time_series_preparation._to_time_index_series(
            period_index_series)
        assert_series_equal(computed_time_series, period_index_series)

    @given(series_with_datetime_index(), st.datetimes(), available_freqs())
    def test_datetime_index_series_unchanged(
        self,
        datetime_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
    ):
        time_series_preparation = TimeSeriesPreparation(start=start, freq=freq)
        computed_time_series = time_series_preparation._to_time_index_series(
            datetime_index_series)
        assert_series_equal(computed_time_series, datetime_index_series)

    @given(series_with_timedelta_index(), st.datetimes(), available_freqs())
    def test_timedelta_index_series_unchanged(
        self,
        timedelta_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
    ):
        time_series_preparation = TimeSeriesPreparation(start=start, freq=freq)
        computed_time_series = time_series_preparation._to_time_index_series(
            timedelta_index_series)
        assert_series_equal(computed_time_series, timedelta_index_series)

    @given(st.tuples())
    def test_wrong_input_type(self, wrong_input: Tuple):
        time_series_preparation = TimeSeriesPreparation()
        with pytest.raises(TypeError):
            time_series_preparation._to_time_index_series(wrong_input)

    @given(series_with_period_index(), st.datetimes(), available_freqs())
    def test_period_index_dataframe_unchanged(
        self,
        period_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
    ):
        period_index_dataframe = pd.DataFrame(period_index_series)
        time_series_preparation = TimeSeriesPreparation(start=start, freq=freq)
        computed_time_series = time_series_preparation._to_time_index_series(
            period_index_dataframe)
        assert_series_equal(computed_time_series, period_index_series)

    @given(series_with_datetime_index(), st.datetimes(), available_freqs())
    def test_datetime_index_dataframe_unchanged(
        self,
        datetime_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
    ):
        datetime_index_dataframe = pd.DataFrame(datetime_index_series)
        time_series_preparation = TimeSeriesPreparation(start=start, freq=freq)
        computed_time_series = time_series_preparation._to_time_index_series(
            datetime_index_dataframe)
        assert_series_equal(computed_time_series, datetime_index_series)

    @given(series_with_timedelta_index(), st.datetimes(), available_freqs())
    def test_timedelta_index_dataframe_unchanged(
        self,
        timedelta_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
    ):
        timedelta_index_dataframe = pd.DataFrame(timedelta_index_series)
        time_series_preparation = TimeSeriesPreparation(start=start, freq=freq)
        computed_time_series = time_series_preparation._to_time_index_series(
            timedelta_index_dataframe)
        assert_series_equal(computed_time_series, timedelta_index_series)
class TestTransform:
    @given(st.lists(st.floats()), st.datetimes(), available_freqs(), st.text())
    def test_list_as_input(
        self,
        input_list: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
        output_name: str,
    ):
        time_series_preparation = TimeSeriesPreparation(
            start=start, freq=freq, output_name=output_name)
        computed_time_series = time_series_preparation.transform(input_list)
        expected_series = pandas_series_with_period_index(input_list,
                                                          start,
                                                          freq=freq)
        expected_time_series = pd.DataFrame({output_name: expected_series})
        assert_frame_equal(computed_time_series, expected_time_series)

    @given(
        arrays(shape=st.integers(0, 1000), dtype=float),
        st.datetimes(),
        available_freqs(),
        st.text(),
    )
    def test_array_as_input(
        self,
        input_array: np.ndarray,
        start: pd.datetime,
        freq: pd.Timedelta,
        output_name: str,
    ):
        time_series_preparation = TimeSeriesPreparation(
            start=start, freq=freq, output_name=output_name)
        computed_time_series = time_series_preparation.transform(input_array)
        expected_series = pandas_series_with_period_index(input_array,
                                                          start,
                                                          freq=freq)
        expected_time_series = pd.DataFrame({output_name: expected_series})
        assert_frame_equal(computed_time_series, expected_time_series)

    @given(series_with_period_index(), st.datetimes(), available_freqs(),
           st.text())
    def test_period_index_as_input(
        self,
        period_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
        output_name: str,
    ):
        time_series_preparation = TimeSeriesPreparation(
            start=start, freq=freq, output_name=output_name)
        computed_time_series = time_series_preparation.transform(
            period_index_series)
        expected_time_series = pd.DataFrame({output_name: period_index_series})
        assert_frame_equal(computed_time_series, expected_time_series)

    @given(series_with_datetime_index(), st.datetimes(), available_freqs(),
           st.text())
    def test_datetime_index_as_input(
        self,
        datetime_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
        output_name: str,
    ):
        time_series_preparation = TimeSeriesPreparation(
            start=start, freq=freq, output_name=output_name)
        computed_time_series = time_series_preparation.transform(
            datetime_index_series)
        expected_series = datetime_index_series_to_period_index_series(
            datetime_index_series, freq=freq)
        expected_time_series = pd.DataFrame({output_name: expected_series})
        assert_frame_equal(computed_time_series, expected_time_series)

    @given(series_with_timedelta_index(), st.datetimes(), available_freqs(),
           st.text())
    def test_timedelta_index_as_input(
        self,
        timedelta_index_series: pd.Series,
        start: pd.datetime,
        freq: pd.Timedelta,
        output_name: str,
    ):
        time_series_preparation = TimeSeriesPreparation(
            start=start, freq=freq, output_name=output_name)
        computed_time_series = time_series_preparation.transform(
            timedelta_index_series)
        expected_series = timedelta_index_series_to_period_index_series(
            timedelta_index_series, freq=freq)
        expected_time_series = pd.DataFrame({output_name: expected_series})
        assert_frame_equal(computed_time_series, expected_time_series)
class TestTimeIndexSeriesToPeriodIndexSeries:
    @settings(suppress_health_check=(HealthCheck.too_slow, ))
    @given(series_with_period_index())
    def test_only_period_index_as_input(self, period_index_series: pd.Series):
        computed_series = transform_time_index_series_into_period_index_series(
            period_index_series)
        expected_series = period_index_series
        assert_series_equal(computed_series, expected_series)

    @given(series_with_period_index(), available_freqs())
    def test_period_index_and_freq_as_input(self,
                                            period_index_series: pd.Series,
                                            freq: pd.Timedelta):
        computed_series = transform_time_index_series_into_period_index_series(
            period_index_series, freq)
        expected_series = period_index_series
        assert_series_equal(computed_series, expected_series)

    @given(series_with_datetime_index())
    def test_only_datetime_index_as_input(self,
                                          datetime_index_series: pd.Series):
        computed_series = transform_time_index_series_into_period_index_series(
            datetime_index_series)
        expected_series = datetime_index_series_to_period_index_series(
            datetime_index_series)
        assert_series_equal(computed_series, expected_series)

    @given(series_with_datetime_index(), available_freqs())
    def test_datetime_index_and_freq_as_input(self,
                                              datetime_index_series: pd.Series,
                                              freq: pd.Timedelta):
        computed_series = transform_time_index_series_into_period_index_series(
            datetime_index_series, freq=freq)
        expected_series = datetime_index_series_to_period_index_series(
            datetime_index_series, freq)
        assert_series_equal(computed_series, expected_series)

    @given(series_with_timedelta_index())
    def test_only_timedelta_index_as_input(self,
                                           timedelta_index_series: pd.Series):
        computed_series = transform_time_index_series_into_period_index_series(
            timedelta_index_series)
        expected_series = timedelta_index_series_to_period_index_series(
            timedelta_index_series)
        assert_series_equal(computed_series, expected_series)

    def test_basic_timedelta_index_as_input(self):
        timedelta_index_series = pd.Series(
            index=pd.timedelta_range(start=pd.Timedelta(days=1),
                                     freq="10D",
                                     periods=3),
            data=[1, 2, 3],
        )
        expected_series = pd.Series(
            index=pd.PeriodIndex(["1970-01-02", "1970-01-12", "1970-01-22"],
                                 freq="D"),
            data=[1, 2, 3],
        )
        computed_series = transform_time_index_series_into_period_index_series(
            timedelta_index_series)
        assert_series_equal(computed_series, expected_series)

    @given(series_with_timedelta_index(), available_freqs())
    def test_timedelta_index_and_freq_as_input(
            self, timedelta_index_series: pd.Series, freq: pd.Timedelta):
        computed_series = transform_time_index_series_into_period_index_series(
            timedelta_index_series, freq=freq)
        expected_series = timedelta_index_series_to_period_index_series(
            timedelta_index_series, freq=freq)
        assert_series_equal(computed_series, expected_series)

    @given(pd_series(dtype=float))
    def test_non_time_index_input(self, series: pd.Series):
        with pytest.raises(ValueError):
            transform_time_index_series_into_period_index_series(series)
class TestListToTimeIndexSeries:
    @given(lists(floats()), datetimes(DEFAULT_START, DEFAULT_END),
           available_freqs())
    def test_list_start_freq_as_input(
        self,
        list_: List[float],
        start: pd.Timestamp,
        freq: pd.Timedelta,
    ):
        compare_output_of_input_sequence_to_expected_one(list_,
                                                         start=start,
                                                         end=None,
                                                         freq=freq)

    @given(lists(floats()), datetimes(DEFAULT_START, DEFAULT_END),
           available_freqs())
    def test_list_end_freq_as_input(
        self,
        list_: List[float],
        end: pd.Timestamp,
        freq: pd.Timedelta,
    ):
        compare_output_of_input_sequence_to_expected_one(list_,
                                                         start=None,
                                                         end=end,
                                                         freq=freq)

    @settings(suppress_health_check=(HealthCheck.too_slow, ))
    @given(lists(floats()), pair_of_ordered_dates())
    def test_error_with_start_end_as_input(
        self,
        list_: List[float],
        start_end: Tuple[pd.Timestamp, pd.Timestamp],
    ):
        with pytest.raises(ValueError):
            compare_output_of_input_sequence_to_expected_one(
                list_,
                *start_end,
                freq=None,
            )

    @given(lists(floats()), pair_of_ordered_dates(), available_freqs())
    def test_too_many_parameters(
        self,
        list_: List[float],
        start_end: Tuple[pd.Timestamp, pd.Timestamp],
        freq: pd.Timedelta,
    ):
        with pytest.raises(ValueError):
            compare_output_of_input_sequence_to_expected_one(
                list_,
                *start_end,
                freq=freq,
            )

    @given(lists(floats()), datetimes(DEFAULT_START, DEFAULT_END))
    def test_list_and_only_start(
        self,
        list_: List[float],
        start: pd.Timestamp,
    ):
        compare_output_of_input_sequence_to_expected_one(list_,
                                                         start=start,
                                                         end=None,
                                                         freq=None)

    @given(lists(floats()), datetimes(DEFAULT_START, DEFAULT_END))
    def test_list_and_only_end(
        self,
        list_: List[float],
        end: pd.Timestamp,
    ):
        compare_output_of_input_sequence_to_expected_one(list_,
                                                         start=None,
                                                         end=end,
                                                         freq=None)

    @given(lists(floats()), available_freqs())
    def test_list_and_only_freq(
        self,
        list_: List[float],
        freq: pd.Timedelta,
    ):
        compare_output_of_input_sequence_to_expected_one(list_,
                                                         start=None,
                                                         end=None,
                                                         freq=freq)

    @given(lists(floats()))
    def test_only_list(
        self,
        list_: List[float],
    ):
        compare_output_of_input_sequence_to_expected_one(list_,
                                                         start=None,
                                                         end=None,
                                                         freq=None)
class TestPandasSeriesToTimeIndexSeries:
    @given(pd_series(dtype=float), datetimes(DEFAULT_START, DEFAULT_END),
           available_freqs())
    def test_series_start_freq_as_input(
        self,
        series: pd.Series,
        start: pd.Timestamp,
        freq: str,
    ):
        compare_output_of_input_series_to_expected_one(
            series,
            start=start,
            end=None,
            freq=freq,
        )

    @given(pd_series(dtype=float), datetimes(DEFAULT_START, DEFAULT_END),
           available_freqs())
    def test_series_end_freq_as_input(
        self,
        series: pd.Series,
        end: pd.Timestamp,
        freq: str,
    ):
        compare_output_of_input_series_to_expected_one(series,
                                                       start=None,
                                                       end=end,
                                                       freq=freq)

    @given(pd_series(dtype=float), pair_of_ordered_dates())
    def test_error_with_start_end_as_input(
        self,
        series: pd.Series,
        start_end: Tuple[pd.Timestamp, pd.Timestamp],
    ):
        with pytest.raises(ValueError):
            compare_output_of_input_series_to_expected_one(
                series,
                *start_end,
                freq=None,
            )

    @given(pd_series(dtype=float), pair_of_ordered_dates(), available_freqs())
    def test_too_many_parameters(
        self,
        series: pd.Series,
        start_end: Tuple[pd.Timestamp, pd.Timestamp],
        freq: str,
    ):
        with pytest.raises(ValueError):
            compare_output_of_input_series_to_expected_one(
                series,
                *start_end,
                freq=freq,
            )

    @given(pd_series(dtype=float), datetimes(DEFAULT_START, DEFAULT_END))
    def test_series_and_only_start(
        self,
        series: pd.Series,
        start: pd.Timestamp,
    ):
        compare_output_of_input_series_to_expected_one(series,
                                                       start=start,
                                                       end=None,
                                                       freq=None)

    @given(pd_series(dtype=float), datetimes(DEFAULT_START, DEFAULT_END))
    def test_series_and_only_end(
        self,
        series: pd.Series,
        end: pd.Timestamp,
    ):
        compare_output_of_input_series_to_expected_one(series,
                                                       start=None,
                                                       end=end,
                                                       freq=None)

    @given(pd_series(dtype=float), available_freqs())
    def test_series_and_only_freq(
        self,
        series: pd.Series,
        freq: pd.Timedelta,
    ):
        compare_output_of_input_series_to_expected_one(series,
                                                       start=None,
                                                       end=None,
                                                       freq=freq)

    @given(pd_series(dtype=float))
    def test_only_series(
        self,
        series: pd.Series,
    ):
        compare_output_of_input_series_to_expected_one(series,
                                                       start=None,
                                                       end=None,
                                                       freq=None)

    @given(series_with_timedelta_index())
    def test_timedelta_index_as_input(self, timedelta_index_series: pd.Series):
        computed_series = transform_series_into_time_index_series(
            timedelta_index_series)
        expected_series = timedelta_index_series
        assert_series_equal(computed_series, expected_series)

    @given(series_with_datetime_index())
    def test_datetime_index_as_input(self, datetime_index_series: pd.Series):
        computed_series = transform_series_into_time_index_series(
            datetime_index_series)
        expected_series = datetime_index_series
        assert_series_equal(computed_series, expected_series)

    @given(series_with_period_index())
    def test_period_index_as_input(self, period_index_series: pd.Series):
        computed_series = transform_series_into_time_index_series(
            period_index_series)
        expected_series = period_index_series
        assert_series_equal(computed_series, expected_series)
class TestArrayToTimeIndexSeries:
    @given(
        arrays(np.float64, integers(0, 1000)),
        datetimes(DEFAULT_START, DEFAULT_END),
        available_freqs(),
    )
    def test_array_start_freq_as_input(
        self,
        array: np.ndarray,
        start: pd.Timestamp,
        freq: str,
    ):
        compare_output_of_input_sequence_to_expected_one(array,
                                                         start=start,
                                                         end=None,
                                                         freq=freq)

    @given(
        arrays(np.float64, integers(0, 1000)),
        datetimes(DEFAULT_START, DEFAULT_END),
        available_freqs(),
    )
    def test_array_end_freq_as_input(
        self,
        array: np.ndarray,
        end: pd.Timestamp,
        freq: str,
    ):
        compare_output_of_input_sequence_to_expected_one(array,
                                                         start=None,
                                                         end=end,
                                                         freq=freq)

    @given(arrays(np.float64, integers(0, 1000)), pair_of_ordered_dates())
    def test_error_with_start_end_as_input(
        self,
        array: np.ndarray,
        start_end: Tuple[pd.Timestamp, pd.Timestamp],
    ):
        with pytest.raises(ValueError):
            compare_output_of_input_sequence_to_expected_one(
                array,
                *start_end,
                freq=None,
            )

    @given(
        arrays(np.float64, integers(0, 1000)),
        pair_of_ordered_dates(),
        available_freqs(),
    )
    def test_too_many_parameters(
        self,
        array: np.ndarray,
        start_end: Tuple[pd.Timestamp, pd.Timestamp],
        freq: str,
    ):
        with pytest.raises(ValueError):
            compare_output_of_input_sequence_to_expected_one(
                array,
                *start_end,
                freq=freq,
            )

    @given(arrays(np.float64, integers(0, 1000)),
           datetimes(DEFAULT_START, DEFAULT_END))
    def test_array_and_only_start(
        self,
        array: np.ndarray,
        start: pd.Timestamp,
    ):
        compare_output_of_input_sequence_to_expected_one(array,
                                                         start=start,
                                                         end=None,
                                                         freq=None)

    @given(arrays(np.float64, integers(0, 1000)),
           datetimes(DEFAULT_START, DEFAULT_END))
    def test_list_and_only_end(
        self,
        array: np.ndarray,
        end: pd.Timestamp,
    ):
        compare_output_of_input_sequence_to_expected_one(array,
                                                         start=None,
                                                         end=end,
                                                         freq=None)

    @given(arrays(np.float64, integers(0, 1000)), available_freqs())
    def test_list_and_only_freq(
        self,
        array: np.ndarray,
        freq: pd.Timedelta,
    ):
        compare_output_of_input_sequence_to_expected_one(array,
                                                         start=None,
                                                         end=None,
                                                         freq=freq)

    @given(arrays(np.float64, integers(0, 1000)))
    def test_only_list(
        self,
        array: np.ndarray,
    ):
        compare_output_of_input_sequence_to_expected_one(array,
                                                         start=None,
                                                         end=None,
                                                         freq=None)