Skip to content

Commit 879b06b

Browse files
authored
Cleanup test_coding_times.py (#9223)
* Cleanup test_coding_times * Update test_coding_times.py
1 parent 3024655 commit 879b06b

File tree

1 file changed

+44
-49
lines changed

1 file changed

+44
-49
lines changed

xarray/tests/test_coding_times.py

+44-49
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,25 @@
1414
Dataset,
1515
Variable,
1616
cftime_range,
17-
coding,
1817
conventions,
1918
date_range,
2019
decode_cf,
2120
)
21+
from xarray.coding.times import _STANDARD_CALENDARS as _STANDARD_CALENDARS_UNSORTED
2222
from xarray.coding.times import (
23+
CFDatetimeCoder,
2324
_encode_datetime_with_cftime,
25+
_netcdf_to_numpy_timeunit,
2426
_numpy_to_netcdf_timeunit,
2527
_should_cftime_be_used,
2628
cftime_to_nptime,
2729
decode_cf_datetime,
2830
decode_cf_timedelta,
2931
encode_cf_datetime,
3032
encode_cf_timedelta,
33+
format_cftime_datetime,
34+
infer_datetime_units,
35+
infer_timedelta_units,
3136
to_timedelta_unboxed,
3237
)
3338
from xarray.coding.variables import SerializationWarning
@@ -53,11 +58,9 @@
5358
"all_leap",
5459
"366_day",
5560
}
56-
_ALL_CALENDARS = sorted(
57-
_NON_STANDARD_CALENDARS_SET.union(coding.times._STANDARD_CALENDARS)
58-
)
61+
_STANDARD_CALENDARS = sorted(_STANDARD_CALENDARS_UNSORTED)
62+
_ALL_CALENDARS = sorted(_NON_STANDARD_CALENDARS_SET.union(_STANDARD_CALENDARS))
5963
_NON_STANDARD_CALENDARS = sorted(_NON_STANDARD_CALENDARS_SET)
60-
_STANDARD_CALENDARS = sorted(coding.times._STANDARD_CALENDARS)
6164
_CF_DATETIME_NUM_DATES_UNITS = [
6265
(np.arange(10), "days since 2000-01-01"),
6366
(np.arange(10).astype("float64"), "days since 2000-01-01"),
@@ -130,7 +133,7 @@ def test_cf_datetime(num_dates, units, calendar) -> None:
130133

131134
with warnings.catch_warnings():
132135
warnings.filterwarnings("ignore", "Unable to decode time axis")
133-
actual = coding.times.decode_cf_datetime(num_dates, units, calendar)
136+
actual = decode_cf_datetime(num_dates, units, calendar)
134137

135138
abs_diff = np.asarray(abs(actual - expected)).ravel()
136139
abs_diff = pd.to_timedelta(abs_diff.tolist()).to_numpy()
@@ -139,17 +142,15 @@ def test_cf_datetime(num_dates, units, calendar) -> None:
139142
# we could do this check with near microsecond accuracy:
140143
# https://github.com/Unidata/netcdf4-python/issues/355
141144
assert (abs_diff <= np.timedelta64(1, "s")).all()
142-
encoded, _, _ = coding.times.encode_cf_datetime(actual, units, calendar)
145+
encoded, _, _ = encode_cf_datetime(actual, units, calendar)
143146

144-
assert_array_equal(num_dates, np.around(encoded, 1))
147+
assert_array_equal(num_dates, np.round(encoded, 1))
145148
if hasattr(num_dates, "ndim") and num_dates.ndim == 1 and "1000" not in units:
146149
# verify that wrapping with a pandas.Index works
147150
# note that it *does not* currently work to put
148151
# non-datetime64 compatible dates into a pandas.Index
149-
encoded, _, _ = coding.times.encode_cf_datetime(
150-
pd.Index(actual), units, calendar
151-
)
152-
assert_array_equal(num_dates, np.around(encoded, 1))
152+
encoded, _, _ = encode_cf_datetime(pd.Index(actual), units, calendar)
153+
assert_array_equal(num_dates, np.round(encoded, 1))
153154

154155

155156
@requires_cftime
@@ -169,7 +170,7 @@ def test_decode_cf_datetime_overflow() -> None:
169170
for i, day in enumerate(days):
170171
with warnings.catch_warnings():
171172
warnings.filterwarnings("ignore", "Unable to decode time axis")
172-
result = coding.times.decode_cf_datetime(day, units)
173+
result = decode_cf_datetime(day, units)
173174
assert result == expected[i]
174175

175176

@@ -178,7 +179,7 @@ def test_decode_cf_datetime_non_standard_units() -> None:
178179
# netCDFs from madis.noaa.gov use this format for their time units
179180
# they cannot be parsed by cftime, but pd.Timestamp works
180181
units = "hours since 1-1-1970"
181-
actual = coding.times.decode_cf_datetime(np.arange(100), units)
182+
actual = decode_cf_datetime(np.arange(100), units)
182183
assert_array_equal(actual, expected)
183184

184185

@@ -193,7 +194,7 @@ def test_decode_cf_datetime_non_iso_strings() -> None:
193194
(np.arange(100), "hours since 2000-01-01 0:00"),
194195
]
195196
for num_dates, units in cases:
196-
actual = coding.times.decode_cf_datetime(num_dates, units)
197+
actual = decode_cf_datetime(num_dates, units)
197198
abs_diff = abs(actual - expected.values)
198199
# once we no longer support versions of netCDF4 older than 1.1.5,
199200
# we could do this check with near microsecond accuracy:
@@ -212,7 +213,7 @@ def test_decode_standard_calendar_inside_timestamp_range(calendar) -> None:
212213
expected = times.values
213214
expected_dtype = np.dtype("M8[ns]")
214215

215-
actual = coding.times.decode_cf_datetime(time, units, calendar=calendar)
216+
actual = decode_cf_datetime(time, units, calendar=calendar)
216217
assert actual.dtype == expected_dtype
217218
abs_diff = abs(actual - expected)
218219
# once we no longer support versions of netCDF4 older than 1.1.5,
@@ -235,9 +236,7 @@ def test_decode_non_standard_calendar_inside_timestamp_range(calendar) -> None:
235236
)
236237
expected_dtype = np.dtype("O")
237238

238-
actual = coding.times.decode_cf_datetime(
239-
non_standard_time, units, calendar=calendar
240-
)
239+
actual = decode_cf_datetime(non_standard_time, units, calendar=calendar)
241240
assert actual.dtype == expected_dtype
242241
abs_diff = abs(actual - expected)
243242
# once we no longer support versions of netCDF4 older than 1.1.5,
@@ -264,7 +263,7 @@ def test_decode_dates_outside_timestamp_range(calendar) -> None:
264263

265264
with warnings.catch_warnings():
266265
warnings.filterwarnings("ignore", "Unable to decode time axis")
267-
actual = coding.times.decode_cf_datetime(time, units, calendar=calendar)
266+
actual = decode_cf_datetime(time, units, calendar=calendar)
268267
assert all(isinstance(value, expected_date_type) for value in actual)
269268
abs_diff = abs(actual - expected)
270269
# once we no longer support versions of netCDF4 older than 1.1.5,
@@ -282,7 +281,7 @@ def test_decode_standard_calendar_single_element_inside_timestamp_range(
282281
for num_time in [735368, [735368], [[735368]]]:
283282
with warnings.catch_warnings():
284283
warnings.filterwarnings("ignore", "Unable to decode time axis")
285-
actual = coding.times.decode_cf_datetime(num_time, units, calendar=calendar)
284+
actual = decode_cf_datetime(num_time, units, calendar=calendar)
286285
assert actual.dtype == np.dtype("M8[ns]")
287286

288287

@@ -295,7 +294,7 @@ def test_decode_non_standard_calendar_single_element_inside_timestamp_range(
295294
for num_time in [735368, [735368], [[735368]]]:
296295
with warnings.catch_warnings():
297296
warnings.filterwarnings("ignore", "Unable to decode time axis")
298-
actual = coding.times.decode_cf_datetime(num_time, units, calendar=calendar)
297+
actual = decode_cf_datetime(num_time, units, calendar=calendar)
299298
assert actual.dtype == np.dtype("O")
300299

301300

@@ -309,9 +308,7 @@ def test_decode_single_element_outside_timestamp_range(calendar) -> None:
309308
for num_time in [days, [days], [[days]]]:
310309
with warnings.catch_warnings():
311310
warnings.filterwarnings("ignore", "Unable to decode time axis")
312-
actual = coding.times.decode_cf_datetime(
313-
num_time, units, calendar=calendar
314-
)
311+
actual = decode_cf_datetime(num_time, units, calendar=calendar)
315312

316313
expected = cftime.num2date(
317314
days, units, calendar, only_use_cftime_datetimes=True
@@ -338,7 +335,7 @@ def test_decode_standard_calendar_multidim_time_inside_timestamp_range(
338335
expected1 = times1.values
339336
expected2 = times2.values
340337

341-
actual = coding.times.decode_cf_datetime(mdim_time, units, calendar=calendar)
338+
actual = decode_cf_datetime(mdim_time, units, calendar=calendar)
342339
assert actual.dtype == np.dtype("M8[ns]")
343340

344341
abs_diff1 = abs(actual[:, 0] - expected1)
@@ -379,7 +376,7 @@ def test_decode_nonstandard_calendar_multidim_time_inside_timestamp_range(
379376

380377
expected_dtype = np.dtype("O")
381378

382-
actual = coding.times.decode_cf_datetime(mdim_time, units, calendar=calendar)
379+
actual = decode_cf_datetime(mdim_time, units, calendar=calendar)
383380

384381
assert actual.dtype == expected_dtype
385382
abs_diff1 = abs(actual[:, 0] - expected1)
@@ -412,7 +409,7 @@ def test_decode_multidim_time_outside_timestamp_range(calendar) -> None:
412409

413410
with warnings.catch_warnings():
414411
warnings.filterwarnings("ignore", "Unable to decode time axis")
415-
actual = coding.times.decode_cf_datetime(mdim_time, units, calendar=calendar)
412+
actual = decode_cf_datetime(mdim_time, units, calendar=calendar)
416413

417414
assert actual.dtype == np.dtype("O")
418415

@@ -435,7 +432,7 @@ def test_decode_non_standard_calendar_single_element(calendar, num_time) -> None
435432

436433
units = "days since 0001-01-01"
437434

438-
actual = coding.times.decode_cf_datetime(num_time, units, calendar=calendar)
435+
actual = decode_cf_datetime(num_time, units, calendar=calendar)
439436

440437
expected = np.asarray(
441438
cftime.num2date(num_time, units, calendar, only_use_cftime_datetimes=True)
@@ -460,9 +457,7 @@ def test_decode_360_day_calendar() -> None:
460457

461458
with warnings.catch_warnings(record=True) as w:
462459
warnings.simplefilter("always")
463-
actual = coding.times.decode_cf_datetime(
464-
num_times, units, calendar=calendar
465-
)
460+
actual = decode_cf_datetime(num_times, units, calendar=calendar)
466461
assert len(w) == 0
467462

468463
assert actual.dtype == np.dtype("O")
@@ -476,8 +471,8 @@ def test_decode_abbreviation() -> None:
476471

477472
val = np.array([1586628000000.0])
478473
units = "msecs since 1970-01-01T00:00:00Z"
479-
actual = coding.times.decode_cf_datetime(val, units)
480-
expected = coding.times.cftime_to_nptime(cftime.num2date(val, units))
474+
actual = decode_cf_datetime(val, units)
475+
expected = cftime_to_nptime(cftime.num2date(val, units))
481476
assert_array_equal(actual, expected)
482477

483478

@@ -498,7 +493,7 @@ def test_decode_abbreviation() -> None:
498493
def test_cf_datetime_nan(num_dates, units, expected_list) -> None:
499494
with warnings.catch_warnings():
500495
warnings.filterwarnings("ignore", "All-NaN")
501-
actual = coding.times.decode_cf_datetime(num_dates, units)
496+
actual = decode_cf_datetime(num_dates, units)
502497
# use pandas because numpy will deprecate timezone-aware conversions
503498
expected = pd.to_datetime(expected_list).to_numpy(dtype="datetime64[ns]")
504499
assert_array_equal(expected, actual)
@@ -510,7 +505,7 @@ def test_decoded_cf_datetime_array_2d() -> None:
510505
variable = Variable(
511506
("x", "y"), np.array([[0, 1], [2, 3]]), {"units": "days since 2000-01-01"}
512507
)
513-
result = coding.times.CFDatetimeCoder().decode(variable)
508+
result = CFDatetimeCoder().decode(variable)
514509
assert result.dtype == "datetime64[ns]"
515510
expected = pd.date_range("2000-01-01", periods=4).values.reshape(2, 2)
516511
assert_array_equal(np.asarray(result), expected)
@@ -531,7 +526,7 @@ def test_decoded_cf_datetime_array_2d() -> None:
531526
def test_infer_datetime_units(freq, units) -> None:
532527
dates = pd.date_range("2000", periods=2, freq=freq)
533528
expected = f"{units} since 2000-01-01 00:00:00"
534-
assert expected == coding.times.infer_datetime_units(dates)
529+
assert expected == infer_datetime_units(dates)
535530

536531

537532
@pytest.mark.parametrize(
@@ -549,7 +544,7 @@ def test_infer_datetime_units(freq, units) -> None:
549544
],
550545
)
551546
def test_infer_datetime_units_with_NaT(dates, expected) -> None:
552-
assert expected == coding.times.infer_datetime_units(dates)
547+
assert expected == infer_datetime_units(dates)
553548

554549

555550
_CFTIME_DATETIME_UNITS_TESTS = [
@@ -573,7 +568,7 @@ def test_infer_datetime_units_with_NaT(dates, expected) -> None:
573568
def test_infer_cftime_datetime_units(calendar, date_args, expected) -> None:
574569
date_type = _all_cftime_date_types()[calendar]
575570
dates = [date_type(*args) for args in date_args]
576-
assert expected == coding.times.infer_datetime_units(dates)
571+
assert expected == infer_datetime_units(dates)
577572

578573

579574
@pytest.mark.filterwarnings("ignore:Timedeltas can't be serialized faithfully")
@@ -600,18 +595,18 @@ def test_cf_timedelta(timedeltas, units, numbers) -> None:
600595
numbers = np.array(numbers)
601596

602597
expected = numbers
603-
actual, _ = coding.times.encode_cf_timedelta(timedeltas, units)
598+
actual, _ = encode_cf_timedelta(timedeltas, units)
604599
assert_array_equal(expected, actual)
605600
assert expected.dtype == actual.dtype
606601

607602
if units is not None:
608603
expected = timedeltas
609-
actual = coding.times.decode_cf_timedelta(numbers, units)
604+
actual = decode_cf_timedelta(numbers, units)
610605
assert_array_equal(expected, actual)
611606
assert expected.dtype == actual.dtype
612607

613608
expected = np.timedelta64("NaT", "ns")
614-
actual = coding.times.decode_cf_timedelta(np.array(np.nan), "days")
609+
actual = decode_cf_timedelta(np.array(np.nan), "days")
615610
assert_array_equal(expected, actual)
616611

617612

@@ -622,7 +617,7 @@ def test_cf_timedelta_2d() -> None:
622617
timedeltas = np.atleast_2d(to_timedelta_unboxed(["1D", "2D", "3D"]))
623618
expected = timedeltas
624619

625-
actual = coding.times.decode_cf_timedelta(numbers, units)
620+
actual = decode_cf_timedelta(numbers, units)
626621
assert_array_equal(expected, actual)
627622
assert expected.dtype == actual.dtype
628623

@@ -637,7 +632,7 @@ def test_cf_timedelta_2d() -> None:
637632
],
638633
)
639634
def test_infer_timedelta_units(deltas, expected) -> None:
640-
assert expected == coding.times.infer_timedelta_units(deltas)
635+
assert expected == infer_timedelta_units(deltas)
641636

642637

643638
@requires_cftime
@@ -653,7 +648,7 @@ def test_infer_timedelta_units(deltas, expected) -> None:
653648
def test_format_cftime_datetime(date_args, expected) -> None:
654649
date_types = _all_cftime_date_types()
655650
for date_type in date_types.values():
656-
result = coding.times.format_cftime_datetime(date_type(*date_args))
651+
result = format_cftime_datetime(date_type(*date_args))
657652
assert result == expected
658653

659654

@@ -1008,7 +1003,7 @@ def test_decode_ambiguous_time_warns(calendar) -> None:
10081003

10091004
# we don't decode non-standard calendards with
10101005
# pandas so expect no warning will be emitted
1011-
is_standard_calendar = calendar in coding.times._STANDARD_CALENDARS
1006+
is_standard_calendar = calendar in _STANDARD_CALENDARS
10121007

10131008
dates = [1, 2, 3]
10141009
units = "days since 1-1-1"
@@ -1043,9 +1038,9 @@ def test_encode_cf_datetime_defaults_to_correct_dtype(
10431038
pytest.skip("Nanosecond frequency is not valid for cftime dates.")
10441039
times = date_range("2000", periods=3, freq=freq)
10451040
units = f"{encoding_units} since 2000-01-01"
1046-
encoded, _units, _ = coding.times.encode_cf_datetime(times, units)
1041+
encoded, _units, _ = encode_cf_datetime(times, units)
10471042

1048-
numpy_timeunit = coding.times._netcdf_to_numpy_timeunit(encoding_units)
1043+
numpy_timeunit = _netcdf_to_numpy_timeunit(encoding_units)
10491044
encoding_units_as_timedelta = np.timedelta64(1, numpy_timeunit)
10501045
if pd.to_timedelta(1, freq) >= encoding_units_as_timedelta:
10511046
assert encoded.dtype == np.int64
@@ -1202,7 +1197,7 @@ def test_decode_float_datetime():
12021197
def test_scalar_unit() -> None:
12031198
# test that a scalar units (often NaN when using to_netcdf) does not raise an error
12041199
variable = Variable(("x", "y"), np.array([[0, 1], [2, 3]]), {"units": np.nan})
1205-
result = coding.times.CFDatetimeCoder().decode(variable)
1200+
result = CFDatetimeCoder().decode(variable)
12061201
assert np.isnan(result.attrs["units"])
12071202

12081203

0 commit comments

Comments
 (0)