2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

pandas.to_datetime: ミリ秒のフォーマットが異なる日時を変換する際、pandas 1.5.3と2.0.1で動作が異なる

Last updated at Posted at 2023-05-01

環境

  • Python 3.11.2
  • pandas 2.0.1

やりたいこと

文字列で表記された日時を、pandas.to_datetime関数でpandasのdatetimeオブジェクトに変換したいです。
ミリ秒のフォーマットは揃っていません。

data = [
    "2023-01-01T15:58:12+09:00",
    "2023-01-01T15:58:12.345+09:00",
]

起きたこと

pandas 1.5.3では以下のコードで、pandasのdatetimeオブジェクトに変換できました。

In [9]: pandas.to_datetime(data)
Out[9]: DatetimeIndex(['2023-01-01 15:58:12+09:00', '2023-01-01 15:58:12.345000+09:00'], dtype='datetime64[ns, pytz.FixedOffset(540)]', freq=None)

しかし、pandas 2.0.1ではValueErrorが発生しました。

In [74]: pandas.to_datetime(data)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

File ~/.pyenv/versions/3.11.2/lib/python3.11/site-packages/pandas/_libs/tslibs/strptime.pyx:351, in pandas._libs.tslibs.strptime.array_strptime()

ValueError: time data "2023-01-01T15:58:12.345+09:00" doesn't match format "%Y-%m-%dT%H:%M:%S%z", at position 1. You might want to try:
    - passing `format` if your strings have a consistent format;
    - passing `format='ISO8601'` if your strings are all ISO8601 but not necessarily in exactly the same format;
    - passing `format='mixed'`, and the format will be inferred for each element individually. You might want to use `dayfirst` alongside this.

原因

当然ではありますが、変数data内の日時のフォーマットが異なるからです。
エラーメッセージを見ると、data[0]から日時フォーマットを%Y-%m-%dT%H:%M:%S%zだと推測して、date[1]2023-01-01T15:58:12.345+09:00をパースしたことが分かります。

つまり、pandas2.0.1では以下のコードでもValueErrorが発生します。

In [75]: pandas.to_datetime("2023-01-01T15:58:12.345+09:00", format="%Y-%m-%dT%H:%M:%S%z")
--------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

しかし、pandas 1.5.3ではエラーは発生しません。

In [15]: pandas.to_datetime("2023-01-01T15:58:12.345+09:00",format= "%Y-%m-%dT%H:%M:%S%z")
Out[15]: Timestamp('2023-01-01 15:58:12.345000+0900', tz='pytz.FixedOffset(540)')

この動きはpandas1.5.3のバグのようです。1

なお、Pythonのdatetimeモジュールではpandas2.0.1と同じ動きになります。

In [21]: datetime.datetime.strptime("2023-01-01T15:58:12.345+09:00",  "%Y-%m-%dT%H:%M:%S%z")
---------------------------------------------------------------------------
ValueError: time data '2023-01-01T15:58:12.345+09:00' does not match format '%Y-%m-%dT%H:%M:%S%z'

解決策

pandas 2.0.0 からはfomat引数にISO8601を指定できます。

“ISO8601”, to parse any ISO8601 time string (not necessarily in exactly the same format);

format="ISO8601"を指定すれば、ミリ秒のフォーマットが異なっていても(ミリ秒以外のフォーマットが異なっていても)pandasのdatetimeオブジェクトに変換できます。

In [78]: pandas.to_datetime(data, format="ISO8601")
Out[78]: DatetimeIndex(['2023-01-01 15:58:12+09:00', '2023-01-01 15:58:12.345000+09:00'], dtype='datetime64[ns, UTC+09:00]', freq=None)
  1. https://github.com/pandas-dev/pandas/issues/53016#issuecomment-1529473807

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?