Skip to content

fix: write timezone-aware coordinates in Model.to_netcdf - #1021

Open
MaykThewessen wants to merge 4 commits into
PyPSA:masterfrom
MaykThewessen:fix/netcdf-tz-aware-coords
Open

MaykThewessen wants to merge 4 commits into
PyPSA:masterfrom
MaykThewessen:fix/netcdf-tz-aware-coords

Conversation

@MaykThewessen

@MaykThewessen MaykThewessen commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Note

AI-assisted. Claude wrote the code and tests, and ran the checks listed below. I reviewed the diff.

Changes proposed in this Pull Request

Follow-up to #897. Since that fix a model with timezone-aware coords builds and solves, but Model.to_netcdf() then raises TypeError: Cannot interpret 'datetime64[us, Europe/Amsterdam]' as a data type, because netCDF has no timezone-aware datetime type. This also breaks solve(remote=...), which goes through to_netcdf. PyPSA runs into it as soon as it allows tz-aware snapshots (PyPSA/PyPSA#983).

to_netcdf now writes tz-aware datetimes as naive UTC and stores the zone names in a _linopy_tz attribute, and read_netcdf restores them. This covers dimension indexes, MultiIndex levels, auxiliary coordinates (the flat-dimension pattern of v1), CSR-backed constraints including their aux coords, and tz-aware data variables in Model.parameters. Files without the attribute read as before.

Checklist

  • AI-generated content is marked (see AGENTS.md).
  • Code changes are sufficiently documented; i.e. new functions contain docstrings and further explanations may be given in doc.
  • Unit tests for new features were added (if applicable).
  • A note for the release notes doc/release_notes.rst of the upcoming release is included.
  • I consent to the release of this PR's code under the MIT license.
What was checked (AI-generated)
  • New test_model_to_netcdf_tz_aware_coords in test/test_io.py, for UTC and Europe/Amsterdam over the 2020-03-29 DST change: flat index, frozen (CSR) constraint and MultiIndex level, plus a tz-aware data variable in Model.parameters. It asserts assert_model_equal and that the timezone comes back. All 10 cases fail on master (the 2 MultiIndex cases under v1 are skipped, like the existing MultiIndex fixture).
  • New test_model_to_netcdf_tz_aware_aux_coords (dense and frozen, 8 cases): all fail on master with the TypeError above. Dense models already drop aux coords on read, also with naive datetimes; that is unchanged here.
  • Full test suite, branch vs master: 5729 vs 5709 passed: the 18 new cases, plus 2 test_highs_keyboard_interrupt tests that failed on the master run only (flaky). The branch has no failures that master lacks; the rest come from the environment (missing oetc extras, HiGHS without SOS).
  • End to end with a PyPSA network on tz-aware snapshots: n.model.to_netcdf() then read_netcdf() gives back equal snapshot indexes with the zone and an equal solution.
  • Not in this PR: freezing a constraint with a MultiIndex dimension already fails on master (Grid.from_dataset, TypeError: Must pass list-like as names), so the test leaves that combination out.

🤖 Generated with Claude Code

netCDF has no timezone-aware datetime type, so to_netcdf raised on
tz-aware coords (dimension indexes, MultiIndex levels, CSR-backed
constraints and data variables in Model.parameters). Write them as
naive UTC with the zone names in a `_linopy_tz` attribute and restore
them in read_netcdf.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codspeed

codspeed Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 181 untouched benchmarks
⏩ 181 skipped benchmarks1


Comparing MaykThewessen:fix/netcdf-tz-aware-coords (a2d2846) with master (1d3c516)

Open in CodSpeed

Footnotes

  1. 181 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

MaykThewessen and others added 2 commits October 7, 2026 16:05
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Auxiliary coordinates with a timezone-aware dtype (the flat-dimension
pattern of v1 semantics) still made to_netcdf raise, in dense datasets
and in the aux coords of CSR constraints. Handle every non-index
variable through one pair of value helpers, and store CSR aux zones as
an attribute on the aux variable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant