2) [H]我如何正确定位幼稚时间? datetime.datetime 使用 my_datetime.localize(pytz_spanish_timezone)
其实,恰恰相反。 localize 是 pytz 时区方法,而不是 datetime 方法:
import pytz
madrid = pytz.timezone('Europe/Madrid')
aware_datetime = madrid.localize(naive_datetime)
您需要datetime.datetime。 datetime.time 对象没有等价物。原因见下文。
3) 如何将一个 datetime.time 对象从一个时区转换为另一个?
考虑以下情况:我们知道时间是 20:30,时区是 Europe/Madrid,我们希望将其转换为 UTC。
结果会有所不同,具体取决于日期是否在夏令时 (CEST) 内 (CET):
例如,
import datetime as DT
import pytz
madrid = pytz.timezone('Europe/Madrid')
utc = pytz.utc
CET_date = madrid.localize(DT.datetime(2019, 3, 30, 20, 30, 0), is_dst=None)
# the most recent transition occurred at `2019-03-31 02:00:00+01:00 CEST`
CEST_date = madrid.localize(DT.datetime(2019, 3, 31, 20, 30, 0), is_dst=None)
print(CET_date.astimezone(utc))
print(CEST_date.astimezone(utc))
# 2019-03-30 19:30:00+00:00
# 2019-03-31 18:30:00+00:00
请注意,当日期为 CET 时,时间 20:30 将“转换”为 19:30,但当日期为 CEST 时,时间将转换为 18:30。
在不知道日期之前,您的问题没有(简单的)答案。
4a) 我应该如何将datetime.time 存储在 postgresql 数据库中?我知道有 time 和 timetz 数据类型。
每the docs:
time with time zone 类型是由 SQL 标准定义的,但该定义显示的属性导致有用性值得怀疑。
我认为文档是在暗示上面显示的问题。不要使用time with
time zone。如果要存储时间,请使用 PostgreSQL 纯 time 类型。
您可以将time 和timezone 存储在数据库中,然后重构
一旦你有一个日期,一个时区感知的日期时间。但请注意,有
陷阱:
-
本地日期时间不明确
import datetime as DT
import pytz
madrid = pytz.timezone('Europe/Madrid')
date = madrid.localize(DT.datetime(2019, 10, 27, 2, 0, 0), is_dst=None)
引发pytz.exceptions.AmbiguousTimeError: 2019-10-27 02:00:00。
为避免AmbiguousTimeError,必须明确指定is_dst:
import datetime as DT
import pytz
madrid = pytz.timezone('Europe/Madrid')
date = madrid.localize(DT.datetime(2019, 10, 27, 2, 0, 0), is_dst=False)
print(date)
date = madrid.localize(DT.datetime(2019, 10, 27, 2, 0, 0), is_dst=True)
print(date)
# 2019-10-27 02:00:00+01:00
# 2019-10-27 02:00:00+02:00
-
本地日期时间不存在
import datetime as DT
import pytz
madrid = pytz.timezone('Europe/Madrid')
madrid.localize(DT.datetime(2019, 3, 31, 2, 0, 0), is_dst=None)
提高pytz.exceptions.NonExistentTimeError: 2019-03-31 02:00:00
您可以通过指定本地时间是否指 DST(夏令时)期间的时间来避免 NonExistentTimeError:
import datetime as DT
import pytz
madrid = pytz.timezone('Europe/Madrid')
date = madrid.normalize(madrid.localize(DT.datetime(2019, 3, 31, 2, 0, 0), is_dst=False))
print(date)
date = madrid.normalize(madrid.localize(DT.datetime(2019, 3, 31, 2, 0, 0), is_dst=True))
print(date)
# 2019-03-31 03:00:00+02:00
# 2019-03-31 01:00:00+01:00
-
在给定本地日期时间和特定时区的情况下,可能存在无法表示的日期时间。
上面的AmbiguousTimeError 和NonExistentTimeError 显示了指定is_dst 值的重要性。
为避免这些错误,您需要在数据库中存储布尔值 is_dst 以及 time 和 timezone。
您可能认为只需选择一个值即可避免该问题
is_dst 永远。但你会弄错的。这是一个特殊的例子
(取自the pytz docs)这表明如果你
总是选择is_dst = False(或is_dst = True)可以有UTC日期时间
仅考虑简单的本地时间和时区就无法表达!
import datetime as DT
import pytz
warsaw = pytz.timezone('Europe/Warsaw')
utc = pytz.utc
date1 = warsaw.localize(DT.datetime(1915, 8, 4, 23, 35, 59), is_dst=False).astimezone(utc)
date2 = warsaw.localize(DT.datetime(1915, 8, 4, 23, 36, 0), is_dst=False).astimezone(utc)
print('Datetimes between {} and {} can not be expressed if we assume is_dist=False.'.format(date1, date2))
date3 = warsaw.localize(DT.datetime(1915, 8, 4, 23, 59, 59), is_dst=True).astimezone(utc)
date4 = warsaw.localize(DT.datetime(1915, 8, 5, 0, 0, 0), is_dst=True).astimezone(utc)
print('Datetimes between {} and {} can not be expressed if we assume is_dist=True.'.format(date1, date2))
打印
Datetimes between 1915-08-04 22:11:59+00:00 and 1915-08-04 22:36:00+00:00 can not be expressed if we assume is_dist=False.
Datetimes between 1915-08-04 22:11:59+00:00 and 1915-08-04 22:36:00+00:00 can not be expressed if we assume is_dist=True.
4b) 我想我应该将时间存储为 UTC。时区重要吗?我应该以某种方式存储它吗?
由于上述原因,UTC 中没有时间(没有日期)。
但是您可以通过简单地将 datetimes 存储在 UTC 中来避免上述问题。
如果您创建的表的列具有 timestamptz 数据类型,那么
您可以使用数据库适配器(例如 psycopg2)来存储 Python 时区感知日期时间
作为 PostgreSQL timestamptzs。当您查询数据库时,psycopg2 会将timestamptzs 转换回
为您提供时区感知的日期时间。
在内部,PostgreSQL 将所有 timestamptzs 存储在 UTC 中,但它会报告与
PostgreSQL 用户的时区设置。在 Python 方面,给定一个时区感知的日期时间,
您可以使用其astimezone 方法将其转换为您喜欢的任何时区。
除非您想报告,否则您不需要单独存储时区
不同时区的不同日期时间。
5) 如何在不经过日期时间的情况下从字符串中解析时间?
您可以使用regex 来解析时间字符串:
import re
import datetime as DT
atime = DT.time(*map(int, re.search(r'(\d{,2}):(\d{,2}):(\d{,2})', 'blueberry jam at 13:32:02').groups()))
print(repr(atime))
# datetime.time(13, 32, 2)
在上面,正则表达式模式\d 匹配一个数字。 \d{1,2} 匹配 1 或 2 位数字。
或者,第三方dateutil package 可以解析
多种格式的时间字符串:
import dateutil.parser as DP
print(DP.parse("13:32:02").time())
# 13:32:02
print(DP.parse("blueberry jam at 13:32:02", fuzzy=True).time())
# 13:32:02
print(DP.parse("30 minutes 12 hours").time())
# 12:30:00
print(DP.parse("2:30pm").time())
# 14:30:00
这里有很多要消化的,可能还有更多可以说的
关于这些问题中的每一个。将来,您可能希望将帖子拆分为
多个问题。这将降低可能希望的人的障碍
回答一个问题,但不是全部,这将帮助您更快地获得更多答案。