如何在 python 中使用带有 datetime 对象的时区?
Posted
技术标签:
【中文标题】如何在 python 中使用带有 datetime 对象的时区?【英文标题】:How do I use timezones with a datetime object in python? 【发布时间】:2010-09-12 03:55:29 【问题描述】:如何在我的时区中正确表示不同的时区?下面的示例仅适用,因为我知道 EDT 比我早一小时,所以我可以取消注释 myTimeZone() 的减法
import datetime, re
from datetime import tzinfo
class myTimeZone(tzinfo):
"""docstring for myTimeZone"""
def utfoffset(self, dt):
return timedelta(hours=1)
def myDateHandler(aDateString):
"""u'Sat, 6 Sep 2008 21:16:33 EDT'"""
_my_date_pattern = re.compile(r'\w+\,\s+(\d+)\s+(\w+)\s+(\d+)\s+(\d+)\:(\d+)\:(\d+)')
day, month, year, hour, minute, second = _my_date_pattern.search(aDateString).groups()
month = [
'JAN', 'FEB', 'MAR',
'APR', 'MAY', 'JUN',
'JUL', 'AUG', 'SEP',
'OCT', 'NOV', 'DEC'
].index(month.upper()) + 1
dt = datetime.datetime(
int(year), int(month), int(day),
int(hour), int(minute), int(second)
)
# dt = dt - datetime.timedelta(hours=1)
# dt = dt - dt.tzinfo.utfoffset(myTimeZone())
return (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, 0, 0, 0)
def main():
print myDateHandler("Sat, 6 Sep 2008 21:16:33 EDT")
if __name__ == '__main__':
main()
【问题讨论】:
看看this answer。希望对您有所帮助! 可以使用email.utils
stdlib 包处理您的特定日期/时间格式:ts = mktime_tz(parsedate_tz('Sat, 6 Sep 2008 21:16:33 EDT'))
【参考方案1】:
Python 标准库不包含时区信息,因为不幸的是,时区数据的变化比 Python 快得多。为此,您需要一个第三方模块;通常的选择是pytz
【讨论】:
这并不能解释为什么标准库不能处理 -500。 这不是正当理由。如果可用,标准库可以使用运行它的平台上的资源,如果找不到时区历史记录,则可以优雅地降级。 @Prof.Falken:如果时区信息不可用,您将如何优雅地降级(引发异常,返回(可能)错误结果,两者)?顺便说一句,见PEP 431: Time zone support improvements @J.F.Sebastian,我不知道。我想到了例外,但我不是 Python 专家。在我看来,事情可能会比现在更好。 PEP 431 对我来说是一个好的开始。【参考方案2】:在使用时区时,我推荐 babel
和 pytz
。保持您的内部日期时间对象天真并使用 UTC 并转换为您的时区以进行格式化。您可能想要简单对象(没有时区信息的对象)的原因是许多库和数据库适配器不知道时区。
【讨论】:
请将 Babel 的链接更新为babel.pocoo.org(如旧网站所说) 还要注意 babel 在 pytz 之上 说“naive and in UTC”是不是很矛盾 @JonCrowell:天真的日期时间对象没有时区信息。您可以将其解释为任何时区的时间(换句话说,它是不明确的),包括 UTC,例如,您可以将2008-09-22 20:59:00
视为 UTC 时间(它是 2008-09-22 13:59:00 PDT-0700
)。【参考方案3】:
对于当前本地时区,您可以使用:
>>> import time
>>> offset = time.timezone if (time.localtime().tm_isdst == 0) else time.altzone
>>> offset / 60 / 60 * -1
-9
返回的值是 UTC 以西的秒数(UTC 以东的区域为负值)。这与我们实际上想要的相反,因此* -1
。
如果夏令时当前未生效,localtime().tm_isdst
将为零(尽管如果某个地区最近更改了夏令时法,这可能不正确)。
【讨论】:
time.timezone
and time.altzone
is not enough in some cases【参考方案4】:
Python >= 3.9
Python 附带zoneinfo 作为标准库的一部分。用法示例:
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
UTC = datetime(2012,11,10,9,0,0, tzinfo=timezone.utc)
# convert to another tz with "astimezone":
eastern = UTC.astimezone(ZoneInfo("US/Eastern"))
# note that it is safe to use "replace",
# to get the same wall time in a different tz:
pacific = eastern.replace(tzinfo=ZoneInfo("US/Pacific"))
print(UTC.isoformat())
print(eastern.isoformat())
print(pacific.isoformat())
# 2012-11-10T09:00:00+00:00
# 2012-11-10T04:00:00-05:00
# 2012-11-10T04:00:00-08:00
另请注意this section from the docs:
zoneinfo 模块不直接提供时区数据,而是从系统时区数据库或第一方 PyPI 包tzdata(如果可用)中提取时区信息。
所以别忘了打电话给pip install tzdata
,至少在 Windows 上是这样。
【讨论】:
以上是关于如何在 python 中使用带有 datetime 对象的时区?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 DataGridViewColumn 中使用服务器 DateTime 格式而不是系统 DateTime 格式
在 SQLite 中使用 DATETIME 列时如何避免 NumberFormatException?
Python。如何使用 datetime.today() 创建本地日期时间