Python datetime и pandas дают разные временные метки для одной и той же даты
from datetime import datetime
import pandas as pd
date="2020-02-07T16:05:16.000000000"
#Convert using datetime
t1=datetime.strptime(date[:-3],'%Y-%m-%dT%H:%M:%S.%f')
#Convert using Pandas
t2=pd.to_datetime(date)
#Subtract the dates
print(t1-t2)
#subtract the date timestamps
print(t1.timestamp()-t2.timestamp())
В этом примере я понимаю, что и datetime, и pandas должны использовать наивные даты с часовым поясом. Может ли кто-нибудь объяснить, почему разница между датами равна нулю, но разница между отметками времени не равна нулю? Для меня он выключен на 5 часов, это смещение моего часового пояса от GMT.
1 ответ
Наивные объекты datetime, производные от Python datetime.datetime
класс представляют местное время. Это отчасти очевидно из документации, но тем не менее может быть головоломкой для работы. Если вы позвоните вtimestamp
метода на нем, возвращенная метка времени POSIX относится к UTC (секунды с эпохи), как и должно.
Исходя из объекта Python datetime, поведение наивного pandas.Timestamp
может быть нелогичным (и я думаю, что это не так очевидно). Полученный таким же образом из tz-наивной строки, он не представляет местное время. Это относится к UTC, если вы называетеtimestamp
метод. В этом можно убедиться, локализовавdatetime
возражать против UTC:
from datetime import datetime, timezone
import pandas as pd
date = "2020-02-07T16:05:16.000000000"
t1 = datetime.strptime(date[:-3], '%Y-%m-%dT%H:%M:%S.%f')
t2 = pd.to_datetime(date)
print(t1.replace(tzinfo=timezone.utc).timestamp()-t2.timestamp())
# 0.0
В противном случае вы можете сделать pandas.Timestamp
с учетом часового пояса, например
t3 = pd.to_datetime(t1.astimezone())
# e.g. Timestamp('2020-02-07 16:05:16+0100', tz='Mitteleuropäische Zeit')
print(t1.timestamp()-t3.timestamp())
# 0.0
Суть в том, что если вы знаете, что метки времени, которые у вас есть, представляют определенный часовой пояс, работайте с датой и временем с учетом часового пояса, например, для UTC
import pytz # need to use pytz here since pandas uses that internally
t1 = datetime.strptime(date[:-3], '%Y-%m-%dT%H:%M:%S.%f').replace(tzinfo=pytz.UTC)
t2 = pd.to_datetime(date, utc=True)
print(t1 == t2)
# True
print(t1-t2)
# 0 days 00:00:00
print(t1.timestamp()-t2.timestamp())
# 0.0