@@ -243,6 +243,27 @@ def _to_ordinalf(dt):
243243_to_ordinalf_np_vectorized = np .vectorize (_to_ordinalf )
244244
245245
246+ def _dt64_to_ordinalf (d ):
247+ """
248+ Convert `numpy.datetime64` or an ndarray of those types to Gregorian
249+ date as UTC float. Roundoff is via float64 precision. Practically:
250+ microseconds for dates between 290301 BC, 294241 AD, milliseconds for
251+ larger dates (see `numpy.datetime64`). Nanoseconds aren't possible
252+ because we do times compared to ``0001-01-01T00:00:00`` (plus one day).
253+ """
254+
255+ # the "extra" ensures that we at least allow the dynamic range out to
256+ # seconds. That should get out to +/-2e11 years.
257+ extra = d - d .astype ('datetime64[s]' )
258+ extra = extra .astype ('timedelta64[ns]' )
259+ t0 = np .datetime64 ('0001-01-01T00:00:00' ).astype ('datetime64[s]' )
260+ dt = (d .astype ('datetime64[s]' ) - t0 ).astype (np .float64 )
261+ dt += extra .astype (np .float64 ) / 1.0e9
262+ dt = dt / SEC_PER_DAY + 1.0
263+
264+ return dt
265+
266+
246267def _from_ordinalf (x , tz = None ):
247268 """
248269 Convert Gregorian float of the date, preserving hours, minutes,
@@ -354,12 +375,13 @@ def date2num(d):
354375
355376 Parameters
356377 ----------
357- d : :class:`datetime` or sequence of :class:`datetime`
378+ d : :class:`datetime` or :class:`numpy.datetime64`, or sequences of
379+ these classes.
358380
359381 Returns
360382 -------
361383 float or sequence of floats
362- Number of days (fraction part represents hours, minutes, seconds)
384+ Number of days (fraction part represents hours, minutes, seconds, ms )
363385 since 0001-01-01 00:00:00 UTC, plus one.
364386
365387 Notes
@@ -368,6 +390,10 @@ def date2num(d):
368390 Gregorian calendar is assumed; this is not universal practice.
369391 For details see the module docstring.
370392 """
393+
394+ if ((isinstance (d , np .ndarray ) and np .issubdtype (d .dtype , np .datetime64 ))
395+ or isinstance (d , np .datetime64 )):
396+ return _dt64_to_ordinalf (d )
371397 if not cbook .iterable (d ):
372398 return _to_ordinalf (d )
373399 else :
@@ -488,8 +514,8 @@ def drange(dstart, dend, delta):
488514 *dend* are :class:`datetime` instances. *delta* is a
489515 :class:`datetime.timedelta` instance.
490516 """
491- f1 = _to_ordinalf (dstart )
492- f2 = _to_ordinalf (dend )
517+ f1 = date2num (dstart )
518+ f2 = date2num (dend )
493519 step = delta .total_seconds () / SEC_PER_DAY
494520
495521 # calculate the difference between dend and dstart in times of delta
@@ -504,7 +530,7 @@ def drange(dstart, dend, delta):
504530 dinterval_end -= delta
505531 num -= 1
506532
507- f2 = _to_ordinalf (dinterval_end ) # new float-endpoint
533+ f2 = date2num (dinterval_end ) # new float-endpoint
508534 return np .linspace (f1 , f2 , num + 1 )
509535
510536### date tickers and formatters ###
@@ -1630,5 +1656,6 @@ def default_units(x, axis):
16301656 return None
16311657
16321658
1659+ units .registry [np .datetime64 ] = DateConverter ()
16331660units .registry [datetime .date ] = DateConverter ()
16341661units .registry [datetime .datetime ] = DateConverter ()
0 commit comments