class TestToPeriodIndex:
    @settings(suppress_health_check=[HealthCheck.filter_too_much])
    @given(series_with_period_index())
    def test_with_period_index_as_input(self, period_index_series):
        time_series_preparation = TimeSeriesPreparation()
        computed_time_series = time_series_preparation._to_period_index_time_series(
            period_index_series)
        assert_series_equal(computed_time_series, period_index_series)

    @given(series_with_datetime_index())
    def test_with_datetime_index_as_input(self, datetime_index_series):
        time_series_preparation = TimeSeriesPreparation()
        computed_time_series = time_series_preparation._to_period_index_time_series(
            datetime_index_series)
        expected_time_series = datetime_index_series_to_period_index_series(
            computed_time_series)
        assert_series_equal(computed_time_series, expected_time_series)

    @given(series_with_timedelta_index())
    def test_with_timedelta_index_as_input(self, timedelta_index_series):
        time_series_preparation = TimeSeriesPreparation()
        computed_time_series = time_series_preparation._to_period_index_time_series(
            timedelta_index_series)
        expected_time_series = timedelta_index_series_to_period_index_series(
            timedelta_index_series)
        assert_series_equal(computed_time_series, expected_time_series)
class TestToPeriodIndexDataFrame:
    @given(series_with_period_index(), st.text())
    def test_output_dataframe_is_correct(self, period_index_series: pd.Series,
                                         output_name: str):
        time_series_preparation = TimeSeriesPreparation(
            output_name=output_name)
        computed_time_series = time_series_preparation._to_period_index_dataframe(
            period_index_series)
        expected_time_series = pd.DataFrame({output_name: period_index_series})
        assert_frame_equal(computed_time_series, expected_time_series)
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 TestPeriodSeries:
    @given(series_with_period_index())
    def test_period_series_has_period_index(self, series):
        assert isinstance(series.index, pd.PeriodIndex)

    @given(series_with_period_index(min_length=10, max_length=1000))
    def test_period_series_size(self, series):
        assert 10 <= len(series.index) <= 1000

    @given(series_with_period_index(min_length=10, max_length=10))
    def test_period_series_size_fixed_value(self, series):
        assert len(series.index) == 10

    @given(series_with_period_index(min_length=0, max_length=0))
    def test_period_series_size_fixed_value_0(self, series):
        assert len(series.index) == 0

    @given(series_with_period_index())
    def test_period_series_boundaries(self, series):
        start_datetime = pd.Period("1979-12-31").to_timestamp()
        end_datetime = pd.Period("2020-01-01").to_timestamp()
        if len(series):
            assert series.index[0].to_timestamp() >= start_datetime
            assert series.index[-1].to_timestamp() <= end_datetime

    @given(series_with_period_index())
    def test_period_series_has_float_values(self, series: pd.Series):
        assert series.dtype == "float64"

    @given(series_with_period_index(allow_nan=False))
    def test_period_series_no_nan(self, series: pd.Series):
        assert_series_equal(series, series.dropna())

    @given(series_with_period_index(allow_infinity=False))
    def test_period_series_no_infinity(self, series: pd.Series):
        assert_series_equal(series, series.replace([np.inf, -np.inf], np.nan))
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 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)