Summary
ms.match() fails when the observation is timezone-aware and the model result is timezone-naive (or vice versa). The failure surfaces as a plain pandas TypeError from deep inside the matching code, with no indication of what actually went wrong.
SCADA exports are often timezone-aware UTC, so users can hit this without realizing their model result and observation disagree on timezone handling.
Root cause
Nothing in the codebase validates or normalizes timezone-awareness. A search of src/modelskill for tz_localize, tz_convert, tzinfo, and timezone returns no matches. The only related time-coordinate handling, _normalize_time_to_ns() (src/modelskill/timeseries/_timeseries.py:42-58), normalizes datetime64 resolution only, not timezone.
The first place a mismatch actually breaks something is observation.trim(period.start, period.end, ...) inside _match_space_time (src/modelskill/matching.py:405), which calls:
data = self.data.sel(time=slice(start_time, end_time)) # _timeseries.py:404
If one side is timezone-aware and the other isn't, this raises:
TypeError: Cannot compare tz-naive and tz-aware datetime-like objects
with no ModelSkill-specific context. The same class of failure can also occur further down the pipeline in align_data() (src/modelskill/timeseries/_align.py:51-85, the interp call on line 80) and TrackModelResult.subset_to() (src/modelskill/model/track.py:74-93, the join call on line 82), if trim doesn't fail first.
Suggested fix
Either:
- Normalize timezone-aware inputs to UTC-naive internally, or
- Validate the mismatch early and raise a clear, ModelSkill-specific error message, with documentation covering this requirement.
Found by a test user evaluating the network functionality ahead of a 1.4.0 release.
Summary
ms.match()fails when the observation is timezone-aware and the model result is timezone-naive (or vice versa). The failure surfaces as a plain pandasTypeErrorfrom deep inside the matching code, with no indication of what actually went wrong.SCADA exports are often timezone-aware UTC, so users can hit this without realizing their model result and observation disagree on timezone handling.
Root cause
Nothing in the codebase validates or normalizes timezone-awareness. A search of
src/modelskillfortz_localize,tz_convert,tzinfo, andtimezonereturns no matches. The only related time-coordinate handling,_normalize_time_to_ns()(src/modelskill/timeseries/_timeseries.py:42-58), normalizes datetime64 resolution only, not timezone.The first place a mismatch actually breaks something is
observation.trim(period.start, period.end, ...)inside_match_space_time(src/modelskill/matching.py:405), which calls:If one side is timezone-aware and the other isn't, this raises:
with no ModelSkill-specific context. The same class of failure can also occur further down the pipeline in
align_data()(src/modelskill/timeseries/_align.py:51-85, theinterpcall on line 80) andTrackModelResult.subset_to()(src/modelskill/model/track.py:74-93, thejoincall on line 82), iftrimdoesn't fail first.Suggested fix
Either:
Found by a test user evaluating the network functionality ahead of a 1.4.0 release.