在涉及日期时间或日期的pygal中试用sample code的XY绘图,1970年之前的任何日期都会导致此追溯:
Traceback (most recent call last):
File "C:/Users/***/dt_test.py", line 30, in <module>
datetimeline.render()
File "C:\Python\Python36\lib\site-packages\pygal\graph\public.py", line 52,
in render
self.setup(**kwargs)
File "C:\Python\Python36\lib\site-packages\pygal\graph\base.py", line 217,
in setup
self._draw()
File "C:\Python\Python36\lib\site-packages\pygal\graph\graph.py", line 924,
in _draw
self._compute_x_labels()
File "C:\Python\Python36\lib\site-packages\pygal\graph\dual.py", line 61,
in _compute_x_labels
self._x_labels = list(zip(map(self._x_format, x_pos), x_pos))
File "C:\Python\Python36\lib\site-packages\pygal\graph\time.py", line 103,
in datetime_to_str
dt = datetime.utcfromtimestamp(x)
OSError: [Errno 22] Invalid argument
有没有其他人得到这种行为? (我正在使用PyCharm。) 也许是千禧年&#39;正在返回意外的负数?
(编辑) 我使用了&#34; date&#34;下的代码,在PyCharm中运行:
from datetime import datetime
datetimeline = pygal.DateTimeLine(
x_label_rotation=35, truncate_label=-1,
x_value_formatter=lambda dt: dt.strftime('%d, %b %Y at %I:%M:%S %p'))
datetimeline.add("Serie", [
(datetime(2013, 1, 2, 12, 0), 300),
(datetime(2013, 1, 12, 14, 30, 45), 412),
(datetime(2013, 2, 2, 6), 823),
(datetime(2013, 2, 22, 9, 45), 672)
])
datetimeline.render()
......当我改变&#39; 2013&#39;至1969年,&#39;我得到了上面显示的Traceback。
答案 0 :(得分:1)
这是由于python用于某些日期和时间处理的基础C函数的限制引起的。这些功能在不同平台上的实现方式有所不同,这就是为什么它不会影响所有人的原因(我不得不借用Windows盒来复制错误)。
docs for datetime.utcfromtimestamp
提到了以下限制:
如果时间戳不在平台C gmtime()函数支持的值范围内,并且在gmtime()失败时出现OSError,则可能会引发OverflowError。通常将其限制在1970年到2038年之间。
幸运的是,相同的文档提出了一种解决方法,并且由于DateTimeLine
类中包含麻烦行的函数太短了,我们可以轻松创建自己的类,该类继承自DateTimeLine
,并且发挥功能。
import pygal
from datetime import datetime, timedelta, timezone
class MyDateTimeLine(pygal.DateTimeLine):
@property
def _x_format(self):
def datetime_to_str(x):
dt = datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=x)
return self.x_value_formatter(dt)
return datetime_to_str
这几乎是从source code for DateTimeLine
复制而来的。唯一的变化是向dt
赋值的行。
我们现在可以使用此类代替DateTimeLine
来绘制2013年或1969年的日期:
formatter = lambda dt: dt.strftime("%d, %b %Y at %I:%M:%S %p")
chart = MyDateTimeLine(x_label_rotation=35, truncate_label=-1,
x_value_formatter=formatter, width=640, height=300)
chart.add("2013", [(datetime(2013, 1, 2, 12, 0), 300),
(datetime(2013, 1, 12, 14, 30, 45), 412),
(datetime(2013, 2, 2, 6), 823),
(datetime(2013, 2, 22, 9, 45), 672)])
chart.render_to_png("chart2013.png")
chart = MyDateTimeLine(x_label_rotation=35, truncate_label=-1,
x_value_formatter=formatter, width=640, height=300)
chart.add("1969", [(datetime(1969, 1, 2, 12, 0), 300),
(datetime(1969, 1, 12, 14, 30, 45), 412),
(datetime(1969, 2, 2, 6), 823),
(datetime(1969, 2, 22, 9, 45), 672)])
chart.render_to_png("chart1969.png")