diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 85cd03f..16e70bb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -59,7 +59,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v4
with:
diff --git a/README.md b/README.md
index e081bf3..6ce1f1b 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ The Jupyter [explorer](https://fdsreader.readthedocs.io/en/latest/guide/explorer
`pip install "fdsreader[notebook]"`. Its command line counterpart needs nothing beyond
numpy and is always installed.
-fdsreader needs Python 3.10 or newer and reads output of FDS 6.7.5 and later; it is tested
+fdsreader needs Python 3.11 or newer and reads output of FDS 6.7.5 and later; it is tested
against the latest FDS release. For complex geometry (`&GEOM`) from FDS 6.10 or newer, use fdsreader 1.12.1 or
later. Details are in the [compatibility table](https://fdsreader.readthedocs.io/en/latest/guide/compatibility.html);
if something does not read correctly, please [open an issue](https://github.com/FireDynamics/fdsreader/issues).
diff --git a/docs/guide/installation.rst b/docs/guide/installation.rst
index 400708b..0161266 100644
--- a/docs/guide/installation.rst
+++ b/docs/guide/installation.rst
@@ -1,7 +1,7 @@
Installation
============
-fdsreader is on `PyPI `_ and needs Python 3.10 or
+fdsreader is on `PyPI `_ and needs Python 3.11 or
newer. Its only dependencies are numpy and typing_extensions.
.. code-block:: sh
diff --git a/fdsreader/simulation.py b/fdsreader/simulation.py
index c6e4060..515b6a3 100644
--- a/fdsreader/simulation.py
+++ b/fdsreader/simulation.py
@@ -5,7 +5,7 @@
import pickle
import re
import warnings
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from typing import AnyStr, Dict, List, Sequence, TextIO, Tuple, Union
import numpy as np
@@ -49,7 +49,7 @@ def _wall_times_to_utc(stamps: Sequence[str]) -> np.ndarray:
for stamp in stamps:
time = datetime.fromisoformat(stamp.strip())
# Without an offset the stamp stays as written; astimezone would assume the local time zone
- utc.append(time.astimezone(timezone.utc).replace(tzinfo=None) if time.tzinfo else time)
+ utc.append(time.astimezone(UTC).replace(tzinfo=None) if time.tzinfo else time)
return np.array(utc, dtype="datetime64[ms]")
diff --git a/pyproject.toml b/pyproject.toml
index baef049..6d7d786 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@ name = "fdsreader"
dynamic = ["version"]
description = "Fast and easy-to-use Python reader for Fire Dynamics Simulator (FDS) output."
readme = "README.md"
-requires-python = ">=3.10"
+requires-python = ">=3.11"
license = "LGPL-3.0-only"
license-files = ["LICENSE", "LICENSE.LESSER"]
authors = [
@@ -26,7 +26,6 @@ maintainers = [
keywords = ["FDS", "Fire Dynamics Simulator", "fire", "fire safety", "CFD", "Smokeview", "simulation", "numpy"]
classifiers = [
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
@@ -101,7 +100,7 @@ testpaths = ["tests"]
[tool.ruff]
line-length = 120
-target-version = "py310"
+target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP"]
diff --git a/tests/test_crash_regressions.py b/tests/test_crash_regressions.py
index 4af84f1..7347a68 100644
--- a/tests/test_crash_regressions.py
+++ b/tests/test_crash_regressions.py
@@ -1,7 +1,6 @@
"""Regression tests for small crashes and warnings found while writing the example notebooks."""
import os
-import sys
import warnings
from pathlib import Path
@@ -14,9 +13,6 @@
CASES_DIR = Path(__file__).parent / "cases"
-# datetime.fromisoformat accepts every ISO 8601 offset only from Python 3.11 on
-_NEEDS_PY311 = pytest.mark.skipif(sys.version_info < (3, 11), reason="fromisoformat needs Python 3.11")
-
@pytest.mark.parametrize("case", ["bndf_data", "bndf_data_fds6100"])
@pytest.mark.parametrize("obst_id", ["Wand_r", "Golf_brandfläche"])
@@ -63,9 +59,9 @@ def test_steps_load_without_timezone_warning(monkeypatch):
("2024-03-14T09:39:53.199-05:30", "2024-03-14T15:09:53.199"),
(" 2024-03-14T09:39:53.199", "2024-03-14T09:39:53.199"),
("2024-03-14", "2024-03-14T00:00:00.000"),
- pytest.param("2024-03-14T09:39:53.199+0100", "2024-03-14T08:39:53.199", marks=_NEEDS_PY311),
- pytest.param("2024-03-14T09:39:53.199+01", "2024-03-14T08:39:53.199", marks=_NEEDS_PY311),
- pytest.param("2024-03-14T09:39:53.199Z", "2024-03-14T09:39:53.199", marks=_NEEDS_PY311),
+ ("2024-03-14T09:39:53.199+0100", "2024-03-14T08:39:53.199"),
+ ("2024-03-14T09:39:53.199+01", "2024-03-14T08:39:53.199"),
+ ("2024-03-14T09:39:53.199Z", "2024-03-14T09:39:53.199"),
],
)
def test_wall_times_to_utc(stamp, utc):