@@ -243,6 +243,27 @@ def _to_ordinalf(dt):
243
243
_to_ordinalf_np_vectorized = np .vectorize (_to_ordinalf )
244
244
245
245
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
+
246
267
def _from_ordinalf (x , tz = None ):
247
268
"""
248
269
Convert Gregorian float of the date, preserving hours, minutes,
@@ -354,12 +375,13 @@ def date2num(d):
354
375
355
376
Parameters
356
377
----------
357
- d : :class:`datetime` or sequence of :class:`datetime`
378
+ d : :class:`datetime` or :class:`numpy.datetime64`, or sequences of
379
+ these classes.
358
380
359
381
Returns
360
382
-------
361
383
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 )
363
385
since 0001-01-01 00:00:00 UTC, plus one.
364
386
365
387
Notes
@@ -368,6 +390,10 @@ def date2num(d):
368
390
Gregorian calendar is assumed; this is not universal practice.
369
391
For details see the module docstring.
370
392
"""
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 )
371
397
if not cbook .iterable (d ):
372
398
return _to_ordinalf (d )
373
399
else :
@@ -488,8 +514,8 @@ def drange(dstart, dend, delta):
488
514
*dend* are :class:`datetime` instances. *delta* is a
489
515
:class:`datetime.timedelta` instance.
490
516
"""
491
- f1 = _to_ordinalf (dstart )
492
- f2 = _to_ordinalf (dend )
517
+ f1 = date2num (dstart )
518
+ f2 = date2num (dend )
493
519
step = delta .total_seconds () / SEC_PER_DAY
494
520
495
521
# calculate the difference between dend and dstart in times of delta
@@ -504,7 +530,7 @@ def drange(dstart, dend, delta):
504
530
dinterval_end -= delta
505
531
num -= 1
506
532
507
- f2 = _to_ordinalf (dinterval_end ) # new float-endpoint
533
+ f2 = date2num (dinterval_end ) # new float-endpoint
508
534
return np .linspace (f1 , f2 , num + 1 )
509
535
510
536
### date tickers and formatters ###
@@ -1630,5 +1656,6 @@ def default_units(x, axis):
1630
1656
return None
1631
1657
1632
1658
1659
+ units .registry [np .datetime64 ] = DateConverter ()
1633
1660
units .registry [datetime .date ] = DateConverter ()
1634
1661
units .registry [datetime .datetime ] = DateConverter ()
0 commit comments