Skip to content

Commit f3d406f

Browse files
authored
fix(zarr-metadata): accept the generic time unit in v2 time dtypes (#4614)
* fix(zarr-metadata): accept the generic time unit in v2 time dtypes NUMPY_TIME_UNITS gains "generic", NumPy's unit-less unit, which NumPy parses in brackets (<M8[generic]) though its own dtype.str omits it, so the v2 reader accepts the bracketed generic spellings zarr-python writes (<M8[generic], <m8[2generic]). The v3 unit tuple already carried generic and now reuses the shared tuple unchanged. A unit is still required: the unitless <M8 stays refused, as the v2 spec demands. Refs #4580 Assisted-by: ClaudeCode:claude-fable-5 * docs(zarr-metadata): changelog fragment for #422 Assisted-by: ClaudeCode:claude-fable-5 * docs(zarr-metadata): number the generic time unit fragment after its PR Assisted-by: ClaudeCode:claude-opus-5-5
1 parent f28c0ad commit f3d406f

4 files changed

Lines changed: 6 additions & 2 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The Zarr format 2 time dtypes accept the generic time unit in brackets — `<M8[generic]`, or `<m8[2generic]` with a scale — the spellings zarr-python writes for a NumPy generic-unit time dtype. A unit is still required: the unitless `<M8` stays refused, as the v2 spec demands.

‎packages/zarr-metadata/src/zarr_metadata/_numpy.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
"ps",
2525
"fs",
2626
"as",
27+
"generic",
2728
)
28-
"""The units NumPy accepts for a datetime64 or timedelta64 (https://numpy.org/doc/stable/reference/arrays.datetime.html#datetime-units). The v3 types also accept `"generic"`."""
29+
"""The units NumPy accepts for a datetime64 or timedelta64 (https://numpy.org/doc/stable/reference/arrays.datetime.html#datetime-units), and `"generic"`, NumPy's unit-less unit, which NumPy parses in brackets (`<M8[generic]`) though its own `dtype.str` omits it. The v2 spec's unit table does not list `generic`, but zarr-python writes it (zarr-developers/zarr-python#4580)."""
2930

3031
NUMPY_TIME_MAX_SCALE_FACTOR: Final = 2**31 - 1
3132
"""The largest `scale_factor` that numpy stores, because the field is a signed int32."""

‎packages/zarr-metadata/src/zarr_metadata/v3/data_type/_numpy_time.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
]
1515
"""The time unit codes of the numpy time types, `numpy.datetime64` and `numpy.timedelta64`."""
1616

17-
NUMPY_TIME_UNIT: Final = (*NUMPY_TIME_UNITS, "generic")
17+
NUMPY_TIME_UNIT: Final = NUMPY_TIME_UNITS
1818
"""Runtime tuple of the permitted `numpy.timedelta64`/`numpy.datetime64` unit strings."""
1919

2020
numpy_time_storage: Final = multi_byte

‎packages/zarr-metadata/tests/v2/test_data_types.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ def _read(value: object) -> tuple[type, list[tuple[Loc, str]]]:
6161
("<M8[ns]", "datetime64", "<M8[ns]"),
6262
(">M8[10s]", "datetime64", ">M8[10s]"),
6363
("<M8[μs]", "datetime64", "<M8[us]"),
64+
("<M8[generic]", "datetime64", "<M8[generic]"),
6465
("<m8[D]", "timedelta64", "<m8[D]"),
66+
(">m8[2generic]", "timedelta64", ">m8[2generic]"),
6567
([["x", "<f4"], ["y", "<i4", [2]]], "struct", (("x", "<f4"), ("y", "<i4", (2,)))),
6668
([["r", "|u1"], ["s", [["t", "<f4"]]]], "struct", (("r", "|u1"), ("s", (("t", "<f4"),)))),
6769
# NumPy names the padding fields of an aligned struct "", and zarr 2.x writes them.

0 commit comments

Comments
 (0)