code: def out_of_time_and_space_splitter(
      train_data: pd.DataFrame,
      n_splits: int,
      in_time_limit: DateType,
      time_column: str,
      space_column: str,
      holdout_gap: timedelta = timedelta(days=0),
  ) -> SplitterReturnType:
      """
      Makes K grouped train/test split folds for cross validation.
      The folds are made so that every ID is used at least once for
      evaluating and K-1 times for training. Also, for each fold, evaluation
      will always be out-of-ID and out-of-time.
  
      Parameters
      ----------
      train_data : pandas.DataFrame
          A Pandas' DataFrame that will be split into K out-of-time and ID
          folds for cross validation.
  
      n_splits : int
          The number of folds K for the K-Fold cross validation strategy.
  
      in_time_limit : str or datetime.datetime
          A String representing the end time of the training data.
          It should be in the same format as the Date column in `train_data`.
  
      time_column : str
          The name of the Date column of `train_data`.
  
      space_column : str
          The name of the ID column of `train_data`.
  
      holdout_gap: datetime.timedelta
          Timedelta of the gap between the end of the training period and the start of the validation period.
      """
  
      # first generate folds by space, using LabelKFold
      # GroupKFold is not supposed to be randomized, that's why there's no random_state here
      train_data = train_data.reset_index()
      space_folds = GroupKFold(n_splits).split(
          train_data, groups=train_data[space_column]
      )
  
      if isinstance(in_time_limit, str):
          in_time_limit = datetime.strptime(in_time_limit, "%Y-%m-%d")
  
      # train_indexes have time_column <= in_time_limit
      # test_indexes have time_column > in_time_limit
      folds = pipe(
          space_folds,
          partial(
              starmap,
              lambda f_train, f_test: [
                  train_data.iloc[f_train][time_column],
                  train_data.iloc[f_test][time_column],
              ],
          ),
          partial(
              starmap,
              lambda train, test: (
                  train[train <= in_time_limit],  # filter train time
                  test[test > (in_time_limit + holdout_gap)],
              ),
          ),  # filter test time
          list,
      )
  
      logs = list(map(_log_time_fold, folds))  # get fold logs
      folds_indexes = _lc_fold_to_indexes(
          folds
      )  # final formatting with idx
      return folds_indexes, logs
  
imports: import operator
  from datetime import datetime, timedelta
  from itertools import chain, repeat, starmap
  from typing import Callable, Iterable, List, Tuple, Union
  import numpy
  import pandas
  from sklearn.model_selection import GroupKFold, KFold, StratifiedKFold
  from sklearn.utils import check_random_state
  from toolz.curried import curry, partial, pipe, assoc, accumulate, map, filter
  from fklearn.common_docstrings import splitter_return_docstring
  from fklearn.types import DateType, LogType, SplitterReturnType
label_desc: Use image node_id 7 for calling a global function with example usage: out_of_time_and_space_splitter(train_data, n_splits, in_time_limit, time_column, space_column, holdout_gap) and returns: folds_indexes,  logs