Description
Bug report
Bug summary
The Axis.broken_barh
function takes an xranges
parameter described as "The x-positions and extends of the rectangles". But if I'm plotting datetime values on the axis, it appears impossible to supply an extent value of a type that the function can deal with.
Using datetime.timedelta
raises an exception AttributeError: 'datetime.timedelta' object has no attribute 'toordinal'
, as does using an integer. Using a datetime
value causes the bar to extend too far (which I guess isn't surprising, as toordinal
on a datetime will not give a duration).
Code for reproduction
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
lo = datetime.fromisoformat("2018-11-09 20:00")
hi = datetime.fromisoformat("2018-11-09 22:00")
fig, ax = plt.subplots()
ax.set_xlim(lo, hi)
ax.set_ylim(0, 30)
ax.broken_barh([(lo, timedelta(hours=1))], (10, 20))
plt.show()
Actual outcome
Traceback (most recent call last):
File ".\problem.py", line 11, in <module>
ax.broken_barh([(lo, timedelta(hours=1))], (10, 20))
File "C:\...\lib\site-packages\matplotlib\__init__.py", line 1810, in inner
return func(ax, *args, **kwargs)
File "C:\...\lib\site-packages\matplotlib\axes\_axes.py", line 2528, in broken_barh
xranges = self.convert_xunits(xranges)
File "C:\...\lib\site-packages\matplotlib\artist.py", line 186, in convert_xunits
return ax.xaxis.convert_units(x)
File "C:\...\lib\site-packages\matplotlib\axis.py", line 1530, in convert_units
ret = self.converter.convert(x, self.units, self)
File "C:\...\lib\site-packages\matplotlib\dates.py", line 1801, in convert
return date2num(value)
File "C:\...\lib\site-packages\matplotlib\dates.py", line 428, in date2num
return _to_ordinalf_np_vectorized(d)
File "C:\...\lib\site-packages\numpy\lib\function_base.py", line 1972, in __call__
return self._vectorize_call(func=func, args=vargs)
File "C:\...\lib\site-packages\numpy\lib\function_base.py", line 2048, in _vectorize_call
outputs = ufunc(*inputs)
File "C:\...\lib\site-packages\matplotlib\dates.py", line 229, in _to_ordinalf
base = float(dt.toordinal())
AttributeError: 'datetime.timedelta' object has no attribute 'toordinal'
Expected outcome
A graph showing a single bar from 20:00 to 21:00.
If this is a limitation of the current version of matplotlib, I'd be perfectly happy with a workaround that gave the expected result by another means (but the approaches I've tried have resulted in the axis tick marks not being correctly formatted as times).
Matplotlib version
- Operating system: Windows 7
- Matplotlib version: 3.0.2
- Matplotlib backend (
print(matplotlib.get_backend())
): TkAgg - Python version: 3.7.1
- Jupyter version (if applicable): N/A
- Other libraries: None
Python installed from the python.org Windows 64-bit installer. Matplotlib installed from the wheel on PyPI (pipenv install matplotlib
).