11from __future__ import annotations
22
33import re
4- import typing
54import warnings
65from collections .abc import Callable , Hashable
76from datetime import datetime , timedelta
@@ -1464,13 +1463,16 @@ def encode(self, variable: Variable, name: T_Name = None) -> Variable:
14641463 ):
14651464 raise ValueError (
14661465 f"Specifying 'add_offset' or 'scale_factor' is not "
1467- f"supported when literally encoding the "
1468- f"np.timedelta64 values of variable { name !r} . To "
1469- f"encode { name !r} with such encoding parameters, "
1470- f"additionally set encoding['units'] to a unit of "
1471- f"time, e.g. 'seconds'. To proceed with literal "
1472- f"np.timedelta64 encoding of { name !r} , remove any "
1473- f"encoding entries for 'add_offset' or 'scale_factor'."
1466+ f"supported when encoding the timedelta64 values of "
1467+ f"variable { name !r} with xarray's new default "
1468+ f"timedelta64 encoding approach. To encode { name !r} "
1469+ f"with xarray's previous timedelta64 encoding "
1470+ f"approach, which supports the 'add_offset' and "
1471+ f"'scale_factor' parameters, additionally set "
1472+ f"encoding['units'] to a unit of time, e.g. "
1473+ f"'seconds'. To proceed with encoding of { name !r} "
1474+ f"via xarray's new approach, remove any encoding "
1475+ f"entries for 'add_offset' or 'scale_factor'."
14741476 )
14751477 if "_FillValue" not in encoding and "missing_value" not in encoding :
14761478 encoding ["_FillValue" ] = np .iinfo (np .int64 ).min
@@ -1497,33 +1499,59 @@ def decode(self, variable: Variable, name: T_Name = None) -> Variable:
14971499 k in encoding for k in _INVALID_LITERAL_TIMEDELTA64_ENCODING_KEYS
14981500 ):
14991501 raise ValueError (
1500- "Decoding np.timedelta64 values via dtype is not "
1501- "supported when 'add_offset', or 'scale_factor' are "
1502- "present in encoding."
1502+ f"Decoding timedelta64 values via dtype is not "
1503+ f"supported when 'add_offset', or 'scale_factor' are "
1504+ f"present in encoding. Check the encoding parameters "
1505+ f"of variable { name !r} ."
15031506 )
15041507 dtype = pop_to (attrs , encoding , "dtype" , name = name )
15051508 dtype = np .dtype (dtype )
15061509 resolution , _ = np .datetime_data (dtype )
1507- if resolution not in typing .get_args (PDDatetimeUnitOptions ):
1508- raise ValueError (
1510+ if np .timedelta64 (1 , resolution ) > np .timedelta64 (1 , "s" ):
1511+ time_unit = cast (PDDatetimeUnitOptions , "s" )
1512+ dtype = np .dtype ("timedelta64[s]" )
1513+ message = (
15091514 f"Following pandas, xarray only supports decoding to "
15101515 f"timedelta64 values with a resolution of 's', 'ms', "
1511- f"'us', or 'ns'. Encoded values have a resolution of "
1512- f"{ resolution !r} ."
1516+ f"'us', or 'ns'. Encoded values for variable { name !r} "
1517+ f"have a resolution of { resolution !r} . Attempting to "
1518+ f"decode to a resolution of 's'. Note, depending on "
1519+ f"the encoded values, this may lead to an "
1520+ f"OverflowError. Additionally, data will not be "
1521+ f"identically round tripped; xarray will choose an "
1522+ f"encoding dtype of 'timedelta64[s]' when re-encoding."
15131523 )
1514- time_unit = cast (PDDatetimeUnitOptions , resolution )
1524+ emit_user_level_warning (message )
1525+ elif np .timedelta64 (1 , resolution ) < np .timedelta64 (1 , "ns" ):
1526+ time_unit = cast (PDDatetimeUnitOptions , "ns" )
1527+ dtype = np .dtype ("timedelta64[ns]" )
1528+ message = (
1529+ f"Following pandas, xarray only supports decoding to "
1530+ f"timedelta64 values with a resolution of 's', 'ms', "
1531+ f"'us', or 'ns'. Encoded values for variable { name !r} "
1532+ f"have a resolution of { resolution !r} . Attempting to "
1533+ f"decode to a resolution of 'ns'. Note, depending on "
1534+ f"the encoded values, this may lead to loss of "
1535+ f"precision. Additionally, data will not be "
1536+ f"identically round tripped; xarray will choose an "
1537+ f"encoding dtype of 'timedelta64[ns]' "
1538+ f"when re-encoding."
1539+ )
1540+ emit_user_level_warning (message )
1541+ else :
1542+ time_unit = cast (PDDatetimeUnitOptions , resolution )
15151543 elif self .decode_via_units :
15161544 if self ._emit_decode_timedelta_future_warning :
15171545 emit_user_level_warning (
15181546 "In a future version, xarray will not decode "
15191547 "timedelta values based on the presence of a "
15201548 "timedelta-like units attribute by default. Instead "
1521- "it will rely on the presence of a np. timedelta64 "
1522- "dtype attribute, which is now xarray's default way "
1523- "of encoding np. timedelta64 values. To continue "
1524- "decoding timedeltas based on the presence of a "
1525- "timedelta-like units attribute, users will need to "
1526- "explicitly opt-in by passing True or "
1549+ "it will rely on the presence of a timedelta64 dtype "
1550+ "attribute, which is now xarray's default way of "
1551+ "encoding timedelta64 values. To continue decoding "
1552+ "timedeltas based on the presence of a timedelta-like "
1553+ "units attribute, users will need to explicitly "
1554+ "opt-in by passing True or "
15271555 "CFTimedeltaCoder(decode_via_units=True) to "
15281556 "decode_timedelta. To silence this warning, set "
15291557 "decode_timedelta to True, False, or a "
0 commit comments