class_docstr: Cutoff window splitter.
  
  Split time series at given cutoff points into a fixed-length training and test set.
  
  Here the user is expected to provide a set of cutoffs (train set endpoints),
  which using the notation provided in :class:`BaseSplitter`,
  can be written as :math:`(k_1,\ldots,k_n)` for integer based indexing,
  or :math:`(t(k_1),\ldots,t(k_n))` for datetime based indexing.
  
  For a cutoff :math:`k_i` and a `window_length` :math:`w`
  the training window is :math:`(k_i-w+1,k_i-w+2,k_i-w+3,\ldots,k_i)`.
  Training window's last point is equal to the cutoff.
  
  Test window is defined by forecasting horizons
  relative to the end of the training window.
  It will contain as many indices
  as there are forecasting horizons provided to the `fh` argument.
  For a forecasting horizon :math:`(h_1,\ldots,h_H)`, the test window will
  consist of the indices :math:`(k_n+h_1,\ldots, k_n+h_H)`.
  
  The number of splits returned by `.get_n_splits`
  is then trivially equal to :math:`n`.
  
  The sorted array of cutoffs returned by `.get_cutoffs` is then equal to
  :math:`(t(k_1),\ldots,t(k_n))` with :math:`k_i<k_{i+1}`.
  
  Parameters
  ----------
  cutoffs : list or np.ndarray or pd.Index
      Cutoff points, positive and integer- or datetime-index like.
      Type should match the type of `fh` input.
  fh : int, timedelta, list or np.ndarray of ints or timedeltas
      Type should match the type of `cutoffs` input.
  window_length : int or timedelta or pd.DateOffset
  
  Examples
  --------
  >>> import numpy as np
  >>> from sktime.split import CutoffSplitter
  >>> ts = np.arange(10)
  >>> splitter = CutoffSplitter(fh=[2, 4], cutoffs=np.array([3, 5]), window_length=3)
  >>> list(splitter.split(ts)) # doctest: +SKIP
  [(array([1, 2, 3]), array([5, 7])), (array([3, 4, 5]), array([7, 9]))]
code: def _split(self, y: pd.Index) -> SPLIT_GENERATOR_TYPE:
      n_timepoints = y.shape[0]
      cutoffs = check_cutoffs(cutoffs=self.cutoffs)
      fh = _check_fh(fh=self.fh)
      window_length = check_window_length(
          window_length=self.window_length, n_timepoints=n_timepoints
      )
      _check_cutoffs_and_y(cutoffs=cutoffs, y=y)
      _check_cutoffs_fh_y(cutoffs=cutoffs, fh=fh, y=y)
  
      for cutoff in cutoffs:
          training_window = _get_train_window_via_endpoint(
              y, cutoff, window_length
          )
          test_window = cutoff + fh.to_numpy()
          if is_datetime(x=cutoff):
              test_window = y.get_indexer(
                  test_window[test_window >= y.min()]
              )
          yield training_window, test_window
  
imports: from typing import Optional
  import numpy
  import pandas
  from sktime.split.base import BaseSplitter
  from sktime.split.base._common import ACCEPTED_Y_TYPES, DEFAULT_FH, DEFAULT_WINDOW_LENGTH, FORECASTING_HORIZON_TYPES, SPLIT_GENERATOR_TYPE, _check_fh, _check_inputs_for_compatibility, _get_train_window_via_endpoint
  from sktime.utils.validation import ACCEPTED_WINDOW_LENGTH_TYPES, array_is_datetime64, array_is_int, check_window_length, is_datetime, is_int, is_timedelta
  from sktime.utils.validation.forecasting import VALID_CUTOFF_TYPES, check_cutoffs
label_desc: Use image node_id 2 for calling the CutoffSplitter obj's underlying member method code with example usage: obj._split(y) without return types