在玩時區轉換和 dst 影響時,我很難弄清楚建構式fold引數的Pandas 實作。檔案提到Timestamp:
由于夏令時,一個掛鐘時間可以在從夏季時間轉換到冬季時間時出現兩次;fold 描述了 datetime-like 是對應于掛鐘的第一次 (0) 還是第二次 (1) 到達不明確的時間。
到目前為止并不奇怪,但是當我運行以下代碼時:
import pandas as pd
from datetime import datetime
pre_fold = pd.Timestamp(datetime(2022,10,30,1,30,0), tz="CET")
in_fold_fold0 = pd.Timestamp(datetime(2022,10,30,2,30,0), tz="CET")
in_fold_fold1 = pd.Timestamp(datetime(2022,10,30,2,30,0), tz="CET", fold=1)
post_fold = pd.Timestamp(datetime(2022,10,30,3,30,0), tz="CET")
print(f"fold0: {in_fold_fold0.fold}")
print(f"fold1: {in_fold_fold1.fold}")
print(f"Pre CET fold: {pre_fold} -> UTC {pre_fold.tz_convert(tz='UTC')}")
print(f"In CET fold, fold0: {in_fold_fold0} -> UTC {in_fold_fold0.tz_convert(tz='UTC')}")
print(f"In CET fold, fold1: {in_fold_fold1} -> UTC {in_fold_fold1.tz_convert(tz='UTC')}")
print(f"Post CET fold: {post_fold} -> UTC {post_fold.tz_convert(tz='UTC')}")
輸出不符合預期:
fold0: 0
fold1: 1
Pre CET fold: 2022-10-30 01:30:00 02:00 -> UTC 2022-10-29 23:30:00 00:00
In CET fold, fold0: 2022-10-30 02:30:00 01:00 -> UTC 2022-10-30 01:30:00 00:00
In CET fold, fold1: 2022-10-30 02:30:00 01:00 -> UTC 2022-10-30 01:30:00 00:00
Post CET fold: 2022-10-30 03:30:00 01:00 -> UTC 2022-10-30 02:30:00 00:00
第 4 行應該是:
In CET fold, fold0: 2022-10-30 02:30:00 02:00 -> UTC 2022-10-30 00:30:00 00:00
我在這里想念什么?
PS:使用 python 的datetime物件會產生預期的輸出:
from datetime import datetime
from dateutil import tz
dt_pre_fold = datetime(2022,10,30,1,30,0, tzinfo=tz.gettz("CET"))
dt_in_fold_fold0 = datetime(2022,10,30,2,30,0, tzinfo=tz.gettz("CET"))
dt_in_fold_fold1 = datetime(2022,10,30,2,30,0, tzinfo=tz.gettz("CET"), fold=1)
dt_post_fold = datetime(2022,10,30,3,30,0, tzinfo=tz.gettz("CET"))
print(f"Pre CET fold: {dt_pre_fold} -> UTC {dt_pre_fold.astimezone(tz.gettz('UTC'))}")
print(f"In CET fold, fold0: {dt_in_fold_fold0} -> UTC {dt_in_fold_fold0.astimezone(tz.gettz('UTC'))}")
print(f"In CET fold, fold1: {dt_in_fold_fold1} -> UTC {dt_in_fold_fold1.astimezone(tz.gettz('UTC'))}")
print(f"Post CET fold: {dt_post_fold} -> UTC {dt_post_fold.astimezone(tz.gettz('UTC'))}")
輸出:
Pre CET fold: 2022-10-30 01:30:00 02:00 -> UTC 2022-10-29 23:30:00 00:00
In CET fold, fold0: 2022-10-30 02:30:00 02:00 -> UTC 2022-10-30 00:30:00 00:00
In CET fold, fold1: 2022-10-30 02:30:00 01:00 -> UTC 2022-10-30 01:30:00 00:00
Post CET fold: 2022-10-30 03:30:00 01:00 -> UTC 2022-10-30 02:30:00 00:00
uj5u.com熱心網友回復:
似乎沒有正確指定時區資訊:
# using your code
x = pd.Timestamp(datetime(2022,10,30,2,30,0), fold = 0, tz="CET")
x.tz_convert('UTC')
# Timestamp('2022-10-30 01:30:00 0000', tz='UTC')
但是如果你使用from dateutil import tz
x = pd.Timestamp(datetime(2022,10,30,2,30,0), fold = 0, tz=tz.gettz("CET"))
x.tz_convert('UTC')
# Timestamp('2022-10-30 00:30:00 0000', tz='UTC')
它回傳正確的值
uj5u.com熱心網友回復:
這種規避了這個問題,但是您可以將時間戳本地化到某個時區,并使用ambiguous關鍵字來指定它應該是 DST 時間還是非 DST 時間,而不是使用“折疊”,來自檔案:
ambiguous [...] bool-ndarray 其中 True 表示 DST 時間,False 表示非 DST 時間(請注意,此標志僅適用于模棱兩可的時間)
所以你可以做你需要的
import pandas as pd
f0 = pd.Timestamp("2022-10-30 02:30:00").tz_localize("Europe/Berlin", ambiguous=True)
f1 = pd.Timestamp("2022-10-30 02:30:00").tz_localize("Europe/Berlin", ambiguous=False)
print(f0.tz_convert('UTC'))
print(f1.tz_convert('UTC'))
# 2022-10-30 00:30:00 00:00 # was DST, UTC 2
# 2022-10-30 01:30:00 00:00 # was non-DST, UTC 1
至于為什么“折疊”不能正常作業,我認為這可以追溯到pandas仍在pytz內部用于時區處理的事實。pytz 不支持 'fold',它使用關鍵字 'is_dst' 代替。您可以在Paul Ganssle的這篇博文中找到更多資訊。pandas src 中也有一些提示。相比之下,dateutil'時區'確實支持'折疊',這可能是@ZLi 的解決方案有效的原因。
旁注:
- 最好使用實際的IANA 時區名稱,以避免縮寫可能有任何歧義
- 不要混合原生 Python 日期時間和 pandas 的日期時間,以避免原生 Python 日期時間的一些粗糙邊緣
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/452711.html
