如何在 Python 中将天真的日期时间转换为可识别 DST 的日期时间?
问题描述
我目前正在开发一个日历系统的后端,该系统返回朴素的 Python 日期时间.前端的工作方式是用户创建各种日历事件,前端返回他们创建的事件的原始版本(例如,如果用户选择 2020 年 10 月 5 日下午 3:00-4:00,则前端返回datetime.datetime(2020, 10, 5, 15, 0, 0)
作为开始,datetime.datetime(2011, 10, 5, 16, 0, 0)
作为结尾.
I'm currently working on the backend for a calendaring system that returns naive Python datetimes. The way the front end works is the user creates various calendar events, and the frontend returns the naive version of the event they created (for example, if the user selects October 5, 2020 from 3:00pm-4:00pm, the frontend returns datetime.datetime(2020, 10, 5, 15, 0, 0)
as the start and datetime.datetime(2011, 10, 5, 16, 0, 0)
as the end.
我需要做的是获取天真的日期时间并将其转换为 UTC 以存储在数据库中.系统的每个用户都已经指定了他们的时区偏好,因此天真的日期时间被认为是与他们的时区偏好相同的时区.显然,日期时间需要相对于 UTC 进行存储,这样如果用户更改时区,现有事件仍将在他们安排的正确时间呈现.
What I need to do is to take the naive datetime and convert it into UTC for storage in a database. Each user of the system has already specified their timezone preference, so the naive datetime is considered to be of the same timezone as their timezone preference. Obviously the datetimes need to be stored relative to UTC so that if users change their timezone, existing events will still render at the correct time that they scheduled them.
前端不在我的控制范围内,因此我无法更改收到的数据.数据库设计也超出了我的控制范围,因此我无法更改存储的数据以及存储方式.
The frontend is outside my control, so I can't change the data that I'm receiving. The database design is also outside my control, so I can't change what data is being stored and how.
这是我目前采取的大致方法:
Here is the approximate approach I have taken so far:
import pytz
def convert_to_UTC(naive_datetime, user_tz_preference):
user_datetime = naive_datetime.replace(tzinfo=user_tz_preference)
utc_datetime = user_datetime.astimezone(pytz.utc)
我遇到的问题与夏令时有关:
The problem I ran into is related to Daylight Savings Time:
>>> from datetime import datetime
>>> import pytz
>>> user_tz_preference = pytz.timezone('US/Pacific')
>>> naive_datetime = datetime(2011, 10, 26, 12, 0, 0)
>>> user_datetime = naive_datetime.replace(tzinfo=user_tz_preference)
>>> user_datetime
datetime.datetime(2011, 10, 26, 12, 0, tzinfo=<DstTzInfo 'US/Pacific' PST-1 day, 16:00:00 STD>)
>>> received_utc = user_datetime.astimezone(pytz.utc)
>>> received_utc
datetime.datetime(2011, 10, 26, 20, 0, tzinfo=<UTC>)
>>> expected_utc = datetime(2011, 10, 26, 19, 0, tzinfo=pytz.utc)
>>> expected_utc == received_utc
False
请注意,无论日期如何,使用替换"都会将时区设置为 PST 而不是 PDT,这使其 UTC 偏移量为 8 小时,而不是预期的 7 小时 DST 偏移量,因此最终会错误地保存时间.
Notice that using 'replace' sets the timezone to PST instead of PDT regardless of the date, which gives it a UTC offset of 8 hours instead of the expected 7 hours DST offset, so the time ends up being saved incorrectly.
我有哪些选项可以将天真的日期时间转换为正确的 PDT(或其他与时区相关的 DST)tzinfo?
What options do I have for converting the naive datetime to the correct PDT (or other timezone-relative DST) tzinfo?
(另外,请注意,并非所有用户都生活在遵守 DST 的时区中,或者可能生活在不同时间切换的时区中,因此为了在保存之前进行时间增量校正等解决方案,我需要了解时区是否支持 DST,以及在哪个日期切换).
(Also, please note that not all users live in a timezone that observes DST, or may live in a timezone that switches over at different times, so in order to do a solution like a timedelta correction before saving, I would need to know if the timezone supports DST, and on which dates it switches over).
解决方案
Pytz 的 localize
函数可以做到这一点:http://pytz.sourceforge.net/#localized-times-and-date-arithmetic
Pytz's localize
function can do this: http://pytz.sourceforge.net/#localized-times-and-date-arithmetic
from datetime import datetime
import pytz
tz = pytz.timezone('US/Pacific')
naive_dt = datetime(2020, 10, 5, 15, 0, 0)
utc_dt = tz.localize(naive_dt, is_dst=None).astimezone(pytz.utc)
# -> 2020-10-05 22:00:00+00:00
相关文章