diff --git a/lib/matplotlib/dates.py b/lib/matplotlib/dates.py index bb7c9ae7fb3f..41a8c5fb2976 100644 --- a/lib/matplotlib/dates.py +++ b/lib/matplotlib/dates.py @@ -444,7 +444,10 @@ def date2num(d): if not iterable: d = [d] + masked = np.ma.is_masked(d) + mask = np.ma.getmask(d) d = np.asarray(d) + # convert to datetime64 arrays, if not already: if not np.issubdtype(d.dtype, np.datetime64): # datetime arrays @@ -458,6 +461,7 @@ def date2num(d): d = np.asarray(d) d = d.astype('datetime64[us]') + d = np.ma.masked_array(d, mask=mask) if masked else d d = _dt64_to_ordinalf(d) return d if iterable else d[0] diff --git a/lib/matplotlib/tests/test_dates.py b/lib/matplotlib/tests/test_dates.py index 43813a161db0..7abebcde7e56 100644 --- a/lib/matplotlib/tests/test_dates.py +++ b/lib/matplotlib/tests/test_dates.py @@ -69,6 +69,26 @@ def test_date2num_NaT_scalar(units): assert np.isnan(tmpl) +def test_date2num_masked(): + # Without tzinfo + base = datetime.datetime(2022, 12, 15) + dates = np.ma.array([base + datetime.timedelta(days=(2 * i)) + for i in range(7)], mask=[0, 1, 1, 0, 0, 0, 1]) + npdates = mdates.date2num(dates) + np.testing.assert_array_equal(np.ma.getmask(npdates), + (False, True, True, False, False, False, + True)) + + # With tzinfo + base = datetime.datetime(2022, 12, 15, tzinfo=mdates.UTC) + dates = np.ma.array([base + datetime.timedelta(days=(2 * i)) + for i in range(7)], mask=[0, 1, 1, 0, 0, 0, 1]) + npdates = mdates.date2num(dates) + np.testing.assert_array_equal(np.ma.getmask(npdates), + (False, True, True, False, False, False, + True)) + + def test_date_empty(): # make sure we do the right thing when told to plot dates even # if no date data has been presented, cf