sdispater / pendulum

Python datetimes made easy
https://pendulum.eustace.io
MIT License
6.22k stars 385 forks source link

Matplotlib support #197

Open BrechtBa opened 6 years ago

BrechtBa commented 6 years ago

Could matplotlib support be added?

import pendulum
import matplotlib.pyplot as plt
datetimes = [
    pendulum.datetime(2018, 5, 1, tz='UTC'),
    pendulum.datetime(2018, 5, 2, tz='UTC'),
    pendulum.datetime(2018, 5, 3, tz='UTC'),
    pendulum.datetime(2018, 5, 4, tz='UTC')
]
values = [0, 1, 2, 3]
fig, ax = plt.subplots()
ax.plot(datetimes, values)

Results in:

TypeError: float() argument must be a string or a number, not 'Pendulum'

The above code is supported by the standard datetime package.

sdispater commented 6 years ago

Strange. It should work since Pendulum's datetime objects inherit directly from native datetime ones.

Could you provide the full stacktrace to see exactly where the error is coming from?

BrechtBa commented 6 years ago
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/__init__.py", line 1898, in inner
    return func(ax, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/axes/_axes.py", line 1407, in plot
    self.add_line(line)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/axes/_base.py", line 1793, in add_line
    self._update_line_limits(line)
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/axes/_base.py", line 1815, in _update_line_limits
    path = line.get_path()
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/lines.py", line 989, in get_path
    self.recache()
  File "/usr/local/lib/python3.5/dist-packages/matplotlib/lines.py", line 676, in recache
    x = np.asarray(xconv, np.float_)
  File "/usr/local/lib/python3.5/dist-packages/numpy/core/numeric.py", line 531, in asarray
    return array(a, dtype, copy=False, order=order)
TypeError: float() argument must be a string or a number, not 'Pendulum'
Delgan commented 6 years ago

Matplotlib doesn't handle datetime subclasses very well: https://github.com/matplotlib/matplotlib/issues/11275

There is a workaround though:

import pendulum
import matplotlib.dates as mdates
import matplotlib.units as munits

munits.registry[pendulum.datetime] = mdates.DateConverter()