feat: add TsFile (Apache IoTDB) packaged builder with per-device wide format

Closes #7922

## Summary

Add a packaged builder for [TsFile](https://tsfile.apache.org/) — the columnar time-series file format used as the native storage layer of [Apache IoTDB](https://iotdb.apache.org/). This enables `load_dataset("tsfile", data_files="...")` with automatic `.tsfile` extension detection.

### Data model

Unlike tabular formats, TsFile is **time-series-aware**: each file contains tables with TAG columns (device identifiers), FIELD columns (measurements), and a TIME column. The builder outputs one dataset row per **device**, where:

- TAG columns are scalar `string` values identifying the device.
- The `time` column and every FIELD column are Arrow `list<...>` columns holding the device's full sorted time series.

```text
<tag_1>:    string
<tag_2>:    string
time:       list<timestamp[unit, tz]>
<field_1>:  list<original_type>
<field_2>:  list<original_type>
```

### Key features

- **Per-device reading** — data is fetched via `TsFileReader.query_table` with a push-down `tag_filter`; peak memory is bounded by a single device's payload, not the entire split.
- **Time-range pushdown** — `start_time` / `end_time` are pushed down to TsFile's internal time index. Accepts `int` epochs, `datetime`, `date`, ISO-8601 strings, and `pyarrow.TimestampScalar`.
- **Schema evolution** — when different files expose different FIELD columns, the loader takes the union and fills missing values with nulls. Numeric types are promoted following IoTDB's widening rules (`INT32 → INT64 → DOUBLE`, `INT32 → FLOAT → DOUBLE`).
- **Case-insensitive table names** — table-name lookups use a canonical lowercase form so auto-detected and user-supplied names always match.
- **`on_bad_files`** — `"error"` (default) / `"warn"` / `"skip"` to control handling of unreadable inputs.
- **Configurable batching** — `input_batch_size` (rows per Arrow batch from the reader) and `output_batch_size` (devices per emitted record batch) for memory control.
- **Timestamp unit & timezone** — `timestamp_unit` (`"s"` / `"ms"` / `"us"` / `"ns"`, default `"ms"`) and `timestamp_tz` (optional timezone string).

### Config knobs (`TsFileConfig`)

| Parameter | Default | Description |
|---|---|---|
| `table_name` | auto-detect | Table to read (case-insensitive) |
| `columns` | all | Subset of FIELD columns to keep; TAGs are always returned |
| `start_time` / `end_time` | unbounded | Inclusive timestamp range, pushed down to TsFile index |
| `input_batch_size` | 65,536 | Max rows per Arrow batch from the reader |
| `output_batch_size` | 32 | Devices per emitted record batch |
| `features` | inferred | Explicit `Features` schema (skips metadata scan) |
| `on_bad_files` | `"error"` | How to handle unreadable files |
| `timestamp_unit` | `"ms"` | Time unit for the timestamp column |
| `timestamp_tz` | `None` | Time zone for the timestamp column |

### Usage

```python
from datasets import load_dataset

# Basic load
ds = load_dataset("tsfile", data_files="my_data.tsfile")

# With options
ds = load_dataset(
    "tsfile",
    data_files="sensor_data.tsfile",
    table_name="sensors",
    columns=["temperature", "humidity"],
    start_time="2024-01-01T00:00:00",
    end_time="2024-12-31T23:59:59",
    timestamp_unit="us",
    timestamp_tz="UTC",
)
```

### Files changed

**New files:**
- `src/datasets/packaged_modules/tsfile/__init__.py` + `tsfile.py` — the builder (770 lines)
- `tests/packaged_modules/test_tsfile.py` — 47 tests (713 lines) covering: basic load, table/column selection, time-range pushdown (all accepted input types), schema evolution and numeric promotion, duplicate-timestamp rejection, multi-file × multi-device crossover, large device with small `input_batch_size`, timezone handling, streaming mode, `on_bad_files` modes, and `_to_epoch` boundary helper.
- `docs/source/tsfile_load.mdx` — standalone Time-series loading guide

**Modified files:**
- `src/datasets/packaged_modules/__init__.py` — register `.tsfile` extension and module entry
- `docs/source/_toctree.yml` — add "Time-series" section to sidebar
- `docs/source/loading.mdx` — add TsFile to the supported formats list and link to the guide
- `docs/source/about_dataset_load.mdx` — add TsFile cross-reference
- `docs/source/package_reference/loading_methods.mdx` — add `TsFileConfig` autodoc entry
- `setup.py` — add `tsfile>=2.3.0` to `TESTS_REQUIRE`

### Dependencies

This builder requires the [`tsfile`](https://pypi.org/project/tsfile/) Python package (`>=2.3.0`), which is added as a test dependency only. The package is lazily imported at runtime — users who don't work with TsFile data pay no import cost.

## Test plan

- [x] 47 unit tests in `tests/packaged_modules/test_tsfile.py`
- [ ] CI passes on the new test suite
- [ ] Documentation renders correctly in the docs build


Hi team 👋

A bit of background on me: I'm a PMC member of both [Apache TsFile](https://tsfile.apache.org/) and [Apache IoTDB](https://iotdb.apache.org/), and one of the core contributors to the TsFile format specification and its Python SDK ([`tsfile` on PyPI](https://pypi.org/project/tsfile/)). I've been working on TsFile's design and implementation for several years, so I'm deeply familiar with its data model, storage internals, and the read path that this builder relies on.

The motivation for this PR is to make time-series data stored in TsFile directly accessible to the HuggingFace ecosystem. TsFile is a columnar format purpose-built for time-series workloads — it powers Apache IoTDB's storage layer and is increasingly used as a standalone interchange format for IoT and industrial data. With the growing interest in applying ML to time-series domains (forecasting, anomaly detection, foundation models, etc.), we believe a native `load_dataset("tsfile", ...)` integration would lower the barrier for researchers and practitioners who already have data in this format.

I'm happy to iterate on the implementation based on your feedback, and I'll be actively maintaining this builder going forward as the TsFile format evolves. Feel free to ping me on any questions about the format or the read semantics.

@lhoestq Would you mind taking a look at this PR when you get a chance? I'd really appreciate your review. Thanks!

Hi @lhoestq, just a friendly ping on this PR again. I'd really appreciate it if you could take a look when you get a chance. Happy to address any feedback or make adjustments if needed. Thanks!

Hi @lhoestq, apologies for the repeated pings — I know you're busy and I really appreciate your time.

I wanted to check if there's anything blocking this PR from being reviewed, or if there's a better person to loop in for an initial pass. I'm totally open to restructuring the PR if it would help — for example, I could split it into a smaller core PR (just the builder + tests) and a follow-up for the docs, if that makes the review more manageable.

The PR adds a packaged builder for [TsFile](https://tsfile.apache.org/), a columnar time-series format from the Apache ecosystem. With the recent surge of interest in time-series foundation models (TimesFM, Chronos, Moirai, etc.), we think a native `load_dataset("tsfile", ...)` would be a nice addition for the community.

Happy to jump on a quick call or chat if that's easier than async review. Thanks again!

Arf it looks like `tsfile` expects pyarrow<20 (for python<3.14) while `datasets` requires pyarrow>=21.0.0

Maybe let's only install tsfile for the py314 CI if you don't mind and remove it from the "tests" extra in setup.py ?

> Arf it looks like `tsfile` expects pyarrow<20 (for python<3.14) while `datasets` requires pyarrow>=21.0.0
> 
> Maybe let's only install tsfile for the py314 CI if you don't mind and remove it from the "tests" extra in setup.py ?

i think it's ok

hi @lhoestq we've done all your suggestions, could you please take a look at this pr again when you're free.

The docs for this PR live [here](https://moon-ci-docs.huggingface.co/docs/datasets/pr_8160). All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

hi @lhoestq, thank you so much for merging this pr, just one more question, when will tsfile appear in the dataset web page of hugging face? Or do you need me to do any other things to make that happend?

<img width="3156" height="1838" alt="image" src="https://github.com/user-attachments/assets/6df9442a-c3af-4a7e-993a-3f24ff7d4d33" />


First we need to index the tsfile datasets on HF, this will be enabled in the coming days, though there is almost no tsfile datasets atm. Then we can add the button there once there are more tsfile datasets on HF

hi @lhoestq , thanks for your explaination, we'll try to upload more tsfile datasets in HF, and when will the dataset viewer be available for tsfile format?

<img width="2156" height="572" alt="image" src="https://github.com/user-attachments/assets/2a948fa5-7fd9-46ac-ba4c-2359c9f0521d" />



> when will the dataset viewer be available for tsfile format?

in the coming days, depending on my bandwidth haha :)

Hi @lhoestq , I’m trying to understand the Dataset Viewer failure I hit when uploading a .tsfile dataset. The traceback shows that the viewer is running on Python 3.12 and fails with ModuleNotFoundError: No module named 'tsfile' when importing from datasets.packaged_modules.tsfile. Could this mean that the Dataset Viewer infrastructure does not currently install the tsfile dependency? Also, I noticed this PR bumps the tsfile version, and if that version requires Python 3.14 while the viewer environment is still Python 3.12, could the Python version mismatch be the reason why the dependency is not available? Would you mind confirming whether this is an infrastructure/dependency issue or something I should change on the dataset side?

<img width="2160" height="1184" alt="image" src="https://github.com/user-attachments/assets/be3461ae-5c0e-4898-9269-d524c296479e" />

yes I haven't deployed it yet, I'll try to do it today

Hi @lhoestq , sorry to bother you again, and thanks again for helping get TsFile support merged.

I wanted to gently follow up on the Dataset Viewer support/deployment for `.tsfile` datasets, since it has been a little while since the last update. The TsFile community has now uploaded 253 datasets to Hugging Face, but at the moment it looks like these datasets still cannot be previewed in the Dataset Viewer. If there is anything we can help with on the TsFile side, we would be very happy to do so.

Also, once TsFile datasets are indexed properly, would it be possible to add `tsfile` as one of the format options on the Hugging Face Datasets page? Given the number of uploaded TsFile datasets, especially within the time-series modality, I think it could help users discover them more easily.

Thanks again for your time!