将数字偏移量转换为时区?

Posted

技术标签:

【中文标题】将数字偏移量转换为时区?【英文标题】:Convert numeric offset to a timezone? 【发布时间】:2021-06-29 19:02:42 【问题描述】:

有一个网站以例如时间的形式提供时区信息。 -07:00。有没有办法可以使用它来本地化 pytz 中的时间戳

通常我会这样做:

EASTERN_TIMEZONE = pytz.timezone("US/Eastern")
date_in_pacific_time = EASTERN_TIMEZONE.localize(my_date)

其中my_date 是某个日期时间日期。但我不知道如何获取一个数字并从中获取时区,因此我可以将其应用于日期并从中获取时间戳。

这可能是一个 XY 问题,因为我想做的是获取一个日期字符串,如 "2021-04-02T18:30:04-07:00" 并将其转换为 Unix UTC 时间戳。

编辑:

像这样?

listing_date_string = "2021-04-02T18:30:04-07:00"
listing_date_string_datepart = listing_date_string[:19]
listing_date_string_timezone = int(listing_date_string[19:].replace(":00", ""))
d = datetime.datetime.strptime(listing_date_string_datepart, '%Y-%m-%dT%H:%M:%S')
d -= datetime.timedelta(hours=listing_date_string_timezone)

print(int(d.timestamp()))  # outputs 1617427804

【问题讨论】:

ISO 格式:%Y-%m-%dT%H:%M:%S%z,所以%z 是您所需要的。 @Simon 好像不匹配,ValueError: time data '2021-04-02T18:30:04-07:00' does not match format '%Y-%m-%dT%H:%M:%S%z' 你的python版本是多少? 【参考方案1】:

Python - 来自docs:

在 3.7 版中更改:当 %z 指令提供给 strptime() 方法,UTC 偏移量可以有一个冒号作为分隔符 在小时、分钟和秒之间。

反之亦然,这意味着对于较旧的 Python 版本,%z 不会解析带有冒号作为小时/分钟分隔符的 UTC 偏移量。你可以像这样解决问题

from datetime import datetime
# your input
s = "2021-04-02T18:30:04-07:00"
# parse separately, colon removed from UTC offset
tz = datetime.strptime(s[19:].replace(':', ''), '%z').tzinfo
dtobj = datetime.strptime(s[:19], "%Y-%m-%dT%H:%M:%S").replace(tzinfo=tz)
print(repr(dtobj))
datetime.datetime(2021, 4, 2, 18, 30, 4, tzinfo=datetime.timezone(datetime.timedelta(-1, 61200)))

如果您知道时区,则可以跳过解析 UTC 偏移量:

import pytz
tz = pytz.timezone('US/Pacific')
dtobj = tz.localize(datetime.strptime(s[:19], "%Y-%m-%dT%H:%M:%S"))
print(repr(dtobj))
datetime.datetime(2021, 4, 2, 18, 30, 4, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)

注意:pytz is deprecated 随着 Python 3.9 的发布 - 您现在在标准库中拥有 zoneinfo。


Python 3.7+ 上,您可以只使用 fromisoformat;

dtobj = datetime.fromisoformat(s)

并从 UTC 偏移量更改为实际时区,例如

dtobj.astimezone(tz) # tz is a timezone object from pytz, dateutil, zoneinfo...
Out[9]: datetime.datetime(2021, 4, 2, 18, 30, 4, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)

【讨论】:

pytz 不再是解决 >2020 时区问题的正确方法,请参阅 bugs.launchpad.net/pytz/+bug/1884458 和 github.com/stub42/pytz/issues/48 中的讨论。 zoneinfo 现在是标准(在一些没有系统范围的时区数据的系统上,如 Windows,以及 tzdata 包),至少建议人们改用 dateutil @deadvoid:我知道一个人应该现在使用zoneinfo...但是:我不认为这是问题的重点。 OP 明确要求使用 pytz。请记住,有很多遗留代码不能只用 zoneinfo 替换 pytz。对于 Python dateutil,因为它遵循与 zoneinfo 相同的语义。 好吧,有 backports.zoneinfo 用于较旧的 python 版本。是的,这确实意味着重构遗留代码,但考虑到人们在这些讨论链接中表达他们的关注的重要性,我认为这是值得的投资。此外,我想在大多数项目中这将是最小的变化并且有助于(至少一点)阻止更多人推广pytz【参考方案2】:

这对你有用吗?

import datetime

dt = datetime.datetime.strptime(
    "2021-04-02T18:30:04-07:00", 
    "%Y-%m-%dT%H:%M:%S%z"
    )
print(
    dt.year,
    dt.month,
    dt.day,
    dt.hour,
    dt.minute,
    dt.second,
    dt.tzinfo,
    )
2021 4 2 18 30 4 UTC-07:00

【讨论】:

不,ValueError: time data '2021-04-02T18:30:04-07:00' does not match format '%Y-%m-%dT%H:%M:%S%z'【参考方案3】:

对于问题 X,一般来说是不可行的。 但是你有一些候选时区,比如

美国/太平洋 美国/凤凰城 美国/山区(与美国/丹佛相同)

所以你可以尝试每一个,看看它是否匹配 -7 小时。

有些日子丹佛在 -7 小时, 在其他日子洛杉矶是-7 小时。 Phoenix一直在 -7 小时

请注意,时区(例如 US/Mountain)与时区偏移量(例如 -7 小时)完全不同。

对于问题 Y,嗯,这很简单! 只需将第一部分视为UTC, 然后应用剩余的 -7 小时修正。

【讨论】:

愚蠢的问题,但 -7 是指“减去 7 以达到 UTC 时间”还是“我们从 UTC 时间返回 7 小时,所以加 7 到那里”? -7 表示位置在格林威治以西,而 +7 表示位置在格林威治以东。正午发生在伦敦~比凤凰城发生早七个小时。如果您的邮票是在凤凰城中午 12 点,加 7 以获得伦敦的 19:00(晚上 7 点)。 我更新了我的 OP,代码 sn-p 是正确的方法吗?

以上是关于将数字偏移量转换为时区?的主要内容,如果未能解决你的问题,请参考以下文章

如何将“GMT + 5.5_(INDIA)”转换为时区“Asia / Kolkata”

如何将UTC时间转化为本地时间

multiboot2 标头在 ELF 文件中“为时已晚”(偏移量很大),即使它是第一部分

如何将 utf-8 字节偏移量转换为 utf-8 字符偏移量

什么是偏移量 怎么计算

将其他时区转换为本地时区(偏移量)