Abstract
dataframe の timezone を Asia/Tokyo に設定しているカラムに datetime.timezone で timezone を設定した datetime instance を代入しようとしたら怒られたときのメモ。
# コード詳細は後述
df.at[idx, 'last_modified_at'] = now
(ommit)
/opt/anaconda3/lib/python3.8/site-packages/pandas/core/arrays/datetimes.py in _check_compatible_with(self, other, setitem)
477 # Stricter check for setitem vs comparison methods
478 if not timezones.tz_compare(self.tz, other.tz):
--> 479 raise ValueError(f"Timezones don't match. '{self.tz}' != '{other.tz}'")
480
481 # -----------------------------------------------------------------
ValueError: Timezones don't match. 'Asia/Tokyo' != 'JST'
まずは解決方法から
timezone の設定は datetime.timezone ではなく pytz を使う。
import pytz
JST = pytz.timezone('Asia/Tokyo')
以下詳細
エラーメッセージを見ての通りだが、両辺の timezone を比較しており、違うと怒られる。
以下、関連する部分のコード抜粋
# read_sql でロードした dataframe のカラムに timezone を設定している
df['created_at'] = df['created_at'].dt.tz_localize(None).dt.tz_localize('Asia/Tokyo')
df['last_modified_at'] = df['last_modified_at'].dt.tz_localize(None).dt.tz_localize('Asia/Tokyo')
from datetime import date, datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9), 'JST')
now = datetime.now(JST)
idx = df[df['id'] == id].index[0]
# エラーになる部分
df.at[idx, 'last_modified_at'] = now
上記 JST を生成している部分を datetime ではなく pytz を使うようにしたら正常に代入できた。
import pytz
JST = pytz.timezone('Asia/Tokyo')
ちなみに、datetime.timezone の第二引数に 'Asia/Tokyo' を指定してみてはどうかと思ってやってみたが、ダメだった。
単純に名前だけの問題ではないらしい。
比較に使われている timezones.tz_compare を調べればわかりそうだけど、pytz を使えばいいや。
JST = timezone(timedelta(hours=+9), 'Asia/Tokyo')
df.at[idx, 'last_modified_at'] = now
ValueError: Timezones don't match. 'Asia/Tokyo' != 'Asia/Tokyo'
なお、tz_localize は 'JST' という指定はできない。
df['created_at'] = df['created_at'].dt.tz_localize(None).dt.tz_localize('JST')
df['last_modified_at'] = df['last_modified_at'].dt.tz_localize(None).dt.tz_localize('JST')
UnknownTimeZoneError: 'JST'
なので右辺を合わせてあげよう。
以上