Code a custom cross-validation splitter that handles time-series data without leaking future information.
Use strictly increasing timestamps and return chronological train and test index pairs. Each test fold must have a fixed size, may be separated from training by a gap, and may optionally limit training-window size.
Function contract: time_series_split(timestamps, n_splits, test_size, gap=0, max_train_size=None) returns a list of [train_indices, test_indices] pairs.
def time_series_split(timestamps, n_splits, test_size, gap=0, max_train_size=None):