Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

[BUG]: NaT inside a datetime64 array serializes as the string "NaT" instead of null

未关闭 适合新手
#5,829 3 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 2 天内回复

@senanurcetin 已经在做这个了。

开始于 2026年10月20日。

  • #5831 来自 @senanurcetin —— 未关闭

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
82/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
numpy, pandas, python

调研方向

阅读 plotly/_plotly_utils/utils.py 中 encode_as_numpy 附近的代码,以及 plotly/io/_json.py 中 clean_to_json_compatible 附近的代码;这两条路径目前都使用 numpy.datetime_as_string 转换 datetime64 数组。在 tests/test_optional/test_utils/test_utils.py 中的 test_pandas_json_encoding 旁边添加 datetime64 测试用例,然后检查两种 JSON 引擎和往返转换。完成标准是 NaT 数组元素序列化为 null,且往返转换后仍为 null。

由索引模型根据 Issue 内容生成。

描述

bug P3 size: 1
Description

At 38374ac, a NaT inside a datetime64 array serializes as the string "NaT" on both engines. The same missing value as a list element or a scalar becomes null, and from_json reads the string back as data.

$ python -I repro.py   # 38374ac, pandas 3.0.6, numpy 2.5.4, orjson 3.13.0
stored : ndarray datetime64[us]
json series -> ['2020-01-01T00:00:00.000000', 'NaT']
json list   -> ['2020-01-01T00:00:00', None]
json scalar -> null
json round  -> ['2020-01-01T00:00:00.000000', 'NaT']
orjson series -> ['2020-01-01T00:00:00.000000', 'NaT']
orjson list   -> ['2020-01-01T00:00:00', None]
orjson scalar -> null
orjson round  -> ['2020-01-01T00:00:00.000000', 'NaT']

plotly.js happens to draw a gap for the string, so a chart looks right. Anything else that reads the figure JSON, such as Dash figure State, gets a string where null belongs.

Screenshots/Video

None: the defect is in the serialized JSON, quoted above.

Steps to reproduce
import json
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio
from plotly.io._json import to_json_plotly

series = pd.Series(pd.to_datetime(["2020-01-01", None]))
fig = go.Figure(go.Scatter(x=series))
print("stored :", type(fig.data[0].x).__name__, fig.data[0].x.dtype)
fig2 = go.Figure(go.Scatter(x=[pd.Timestamp("2020-01-01"), pd.NaT]))
for e in ("json", "orjson"):
    print(e, "series ->", json.loads(pio.to_json(fig, engine=e))["data"][0]["x"])
    print(e, "list   ->", json.loads(pio.to_json(fig2, engine=e))["data"][0]["x"])
    print(e, "scalar ->", to_json_plotly(pd.NaT, engine=e))
    print(e, "round  ->", list(pio.from_json(pio.to_json(fig, engine=e), engine=e).data[0].x))
Notes

contract: tests/test_optional/test_utils/test_utils.py:276 already asserts null for pd.NaT inside an object-dtype Series, and :291 asserts "[null]" for [pd.NaT]. The datetime64 dtype of that same Series breaks the promise. The scalar case is tests/test_io/test_to_from_plotly_json.py:265.

The json engine (the auto fallback when orjson is absent) goes through encode_as_numpy at _plotly_utils/utils.py:297, and orjson goes through clean_to_json_compatible at plotly/io/_json.py:517. Both call datetime_as_string unfiltered:

-                return numpy.datetime_as_string(obj).tolist()
+                return [
+                    None if s == "NaT" else s
+                    for s in numpy.datetime_as_string(obj).tolist()
+                ]
$ python -I repro.py | grep -E "series|round"   # filter at utils.py:297 only
json series -> ['2020-01-01T00:00:00.000000', None]
json round  -> ['2020-01-01T00:00:00.000000', None]
orjson series -> ['2020-01-01T00:00:00.000000', 'NaT']
orjson round  -> ['2020-01-01T00:00:00.000000', 'NaT']
$ python -I repro.py | grep -E "series|round"   # same filter at _json.py:517 too
json series -> ['2020-01-01T00:00:00.000000', None]
json round  -> ['2020-01-01T00:00:00.000000', None]
orjson series -> ['2020-01-01T00:00:00.000000', None]
orjson round  -> ['2020-01-01T00:00:00.000000', None]
# reverted: all four lines print 'NaT' again

No CODEOWNERS entry covers these paths. @camdecoster, would you take a PR with the filter at both sites and a datetime64 case next to test_pandas_json_encoding?

主要语言
Python
星标
18.9k
派生
2.9k
平均合并
2 天 7 小时
30 天内合并 PR
12

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

plotly/plotly.py 的其他 Issue

查看 plotly/plotly.py 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。