You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib时间戳转日期格式触发OverflowError问题求助

解决Matplotlib中Epoch秒级时间戳转日期格式的OverflowError问题

我想用Matplotlib把图表X轴的Epoch秒级时间戳转换成%Y-%m-%d %H:%M格式,按照官方文档操作后出现了OverflowError,相关报错回溯、代码和时间轴示例数据如下:

报错回溯

Traceback (most recent call last):
  File "/home/andreas/src/masiri/booking_algorythm/simple_booking.py", line 277, in <module>
    main()
  File "/home/andreas/src/masiri/booking_algorythm/simple_booking.py", line 273, in main
    accepted_list_of_bookings, accepted_bookings_a = process_booking_requests(randomized_list_of_bookings)
  File "/home/andreas/src/masiri/booking_algorythm/simple_booking.py", line 257, in process_booking_requests
    price = calculate_price_for_booking(trip_request, sequential_trip_requests,
  File "/home/andreas/src/masiri/booking_algorythm/simple_booking.py", line 226, in calculate_price_for_booking
    old_price = turn_booking_into_charging_plan(start_time, end_time, old_bookings_list)
  File "/home/andreas/src/masiri/booking_algorythm/simple_booking.py", line 209, in turn_booking_into_charging_plan
    plot_solution(sub_metric_v, soc_plot, charge_plot, discharge_plot, bookings_list, instability_ranges)
  File "/home/andreas/src/masiri/booking_algorythm/simple_booking.py", line 195, in plot_solution
    fig.autofmt_xdate()
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/figure.py", line 249, in autofmt_xdate
    for label in ax.get_xticklabels(which=which):
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 73, in wrapper
    return get_method(self)(*args, **kwargs)
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/axis.py", line 1381, in get_ticklabels
    return self.get_majorticklabels()
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/axis.py", line 1345, in get_majorticklabels
    self._update_ticks()
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/axis.py", line 1191, in _update_ticks
    major_labels = self.major.formatter.format_ticks(major_locs)
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/ticker.py", line 233, in format_ticks
    return [self(value, i) for i, value in enumerate(values)]
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/ticker.py", line 233, in <listcomp>
    return [self(value, i) for i, value in enumerate(values)]
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/dates.py", line 640, in __call__
    result = num2date(x, self.tz).strftime(self.fmt)
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/dates.py", line 533, in num2date
    return _from_ordinalf_np_vectorized(x, tz).tolist()
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/numpy/lib/function_base.py", line 2328, in __call__
    return self._vectorize_call(func=func, args=vargs)
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/numpy/lib/function_base.py", line 2411, in _vectorize_call
    outputs = ufunc(*inputs)
  File "/home/andreas/src/masiri/venv/lib/python3.10/site-packages/matplotlib/dates.py", line 354, in _from_ordinalf
    np.timedelta64(int(np.round(x * MUSECONDS_PER_DAY)), 'us'))
OverflowError: int too big to convert

相关代码

def plot_solution(data, soc_plot,charge_plot, discharge_plot, bookings=None, boundaries=None):
    my_fmt = mdates.DateFormatter('%Y-%m-%d %H:%M')
    fig, ax_left = plt.subplots()
    ax_right = ax_left.twinx()
    ax_left.xaxis.set_major_formatter(my_fmt)
    ax_right.xaxis.set_major_formatter(my_fmt)
    time_axis = data["time"]

    ax_right.plot(time_axis, soc_plot, label="State of Charge")
    ax_left.plot(time_axis, data["price"], label="price (€/kWs)")
    ax_left.plot(time_axis, data["price_co2"], label="price including CO_2 costs (€/kWs)")
    #ax_right.plot(data["time"], charge_plot, label="charge")
    #ax_right.plot(data["time"], discharge_plot, label="discharge")
    bookings_flag = True
    if bookings is not None:
        for booking in bookings:
            if bookings_flag:
                ax_left.axvspan(booking["start"], booking["start"] + booking["duration"], facecolor='0.4', alpha=0.5, label="booking")
                bookings_flag = False
            else:
                ax_left.axvspan(booking["start"], booking["start"] + booking["duration"], facecolor='0.4', alpha=0.5, label="booking")
    boundaries_flag = True
    if boundaries is not None:
        for boundary in boundaries:
            if boundaries_flag:
                ax_left.axvspan(time_axis[boundary["start"]], time_axis[boundary["end"]], facecolor='0.9', alpha=0.5, label="boundary")
                boundaries_flag = False
            else:
                ax_left.axvspan(time_axis[boundary["start"]], time_axis[boundary["end"]], facecolor='0.9', alpha=0.5)
    ax_left.set_xlabel("time in seconds")
    ax_left.set_ylabel("price in €/kWs", color="blue")
    ax_right.set_ylabel("State of Charge (SoC), normalized", color="black")
    legend_1 = ax_left.legend(loc=2, borderaxespad=1.)
    legend_1.remove()
    ax_right.legend(loc=1, borderaxespad=1.)
    ax_right.add_artist(legend_1)
    fig.autofmt_xdate()
    plt.show(block=True)

时间轴示例数据

>>> time_axis
array([1635905700, 1635906600, 1635907500, 1635908400, 1635909300,
       1635910200, 1635911100, 1635912000, 1635912900, 1635913800,

问题原因

Matplotlib的DateFormatter默认处理的是Matplotlib内部的日期数值(以天为单位,从0001年开始计算),而你传入的是Epoch秒级时间戳(从1970年开始的秒数),数值过大导致转换时溢出。

解决方案

方法1:用epoch2num转换时间戳

将所有X轴相关的秒级时间戳,通过mdates.epoch2num()转换成Matplotlib可识别的日期数值,修改后的代码如下:

def plot_solution(data, soc_plot,charge_plot, discharge_plot, bookings=None, boundaries=None):
    my_fmt = mdates.DateFormatter('%Y-%m-%d %H:%M')
    fig, ax_left = plt.subplots()
    ax_right = ax_left.twinx()
    
    # 关键:把Epoch秒级时间戳转成Matplotlib日期数值
    time_axis = mdates.epoch2num(data["time"])

    ax_right.plot(time_axis, soc_plot, label="State of Charge")
    ax_left.plot(time_axis, data["price"], label="price (€/kWs)")
    ax_left.plot(time_axis, data["price_co2"], label="price including CO_2 costs (€/kWs)")
    
    bookings_flag = True
    if bookings is not None:
        for booking in bookings:
            # 同步转换booking的时间戳
            start = mdates.epoch2num(booking["start"])
            end = mdates.epoch2num(booking["start"] + booking["duration"])
            if bookings_flag:
                ax_left.axvspan(start, end, facecolor='0.4', alpha=0.5, label="booking")
                bookings_flag = False
            else:
                ax_left.axvspan(start, end, facecolor='0.4', alpha=0.5)
    boundaries_flag = True
    if boundaries is not None:
        for boundary in boundaries:
            # 转换boundary对应的时间戳
            start = mdates.epoch2num(data["time"][boundary["start"]])
            end = mdates.epoch2num(data["time"][boundary["end"]])
            if boundaries_flag:
                ax_left.axvspan(start, end, facecolor='0.9', alpha=0.5, label="boundary")
                boundaries_flag = False
            else:
                ax_left.axvspan(start, end, facecolor='0.9', alpha=0.5)
    
    ax_left.xaxis.set_major_formatter(my_fmt)
    ax_right.xaxis.set_major_formatter(my_fmt)
    ax_left.set_xlabel("time")
    ax_left.set_ylabel("price in €/kWs", color="blue")
    ax_right.set_ylabel("State of Charge (SoC), normalized", color="black")
    legend_1 = ax_left.legend(loc=2, borderaxespad=1.)
    legend_1.remove()
    ax_right.legend(loc=1, borderaxespad=1.)
    ax_right.add_artist(legend_1)
    fig.autofmt_xdate()
    plt.show(block=True)

方法2:转成numpy.datetime64类型

如果你的Python版本支持,也可以直接把时间戳转成numpy.datetime64类型,Matplotlib会自动识别这种格式:

# 替换time_axis的定义
time_axis = np.array(data["time"], dtype='datetime64[s]')

同时axvspan里的时间参数也要同步转成datetime64类型,比如:

start = np.datetime64(booking["start"], 's')
end = np.datetime64(booking["start"] + booking["duration"], 's')

注意事项

所有X轴相关的时间参数(比如axvspan的起止值)必须统一格式,不能混合原始秒级戳和转换后的数值。


内容的提问来源于stack exchange,提问作者Andreas Schuldei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:12:06