从时区和 UTC 时间,获取该时间点与本地时间的秒差
Posted
技术标签:
【中文标题】从时区和 UTC 时间,获取该时间点与本地时间的秒差【英文标题】:From a timezone and a UTC time, get the difference in seconds vs local time at that point in time 【发布时间】:2012-09-23 08:28:41 【问题描述】:这应该很简单,但我在 Python 中无法完全弄清楚。 我想要一个函数,它接受两个参数,一个 UTC 时间(以秒为单位)和一个 zoneinfo name(如 'Europe/Vienna'),并以秒为单位返回与本地时间的偏移量和该时间点的 UTC。
在 C 中应该是:
/* ... code to to set local time to the time zone I want to compare against,
not shown here. Then call function below to get difference vs localtime.
Hardly an ideal solution,
but just to demonstrate what I want in a "lingua franca" (C): */
int get_diff_vs_localtime(const time_t original_utc_time)
struct tm* ts;
ts = localtime(&original_utc_time);
return mktime(ts) - original_utc_time;
我想我的问题真的可以归结为:“给定 Olson timezone(例如 'Europe/Stockholm')和 UTC 时间,当地时间是多少?
【问题讨论】:
***.com/questions/6801429/…***.com/questions/79797/…***.com/questions/4115310/…***.com/questions/6377179/…***.com/questions/10524165/…***.com/questions/4770297/…可能相关 niemeyer.net/python-dateutil 我召唤@JonSkeet 的力量! 我查看了您提供的链接(针对其他 SO 问题)。当心他们都没有正确处理与 DST 相关的问题。 @J.F.Sebastian,你很有野心。你的意思是他们都没有或只有一些? 【参考方案1】:我想我的问题真的可以归结为:“鉴于奥尔森时区 (例如“欧洲/斯德哥尔摩”)和 UTC 时间,当地时间是多少?
如果我正确理解您的问题:
from pytz import timezone
import datetime, time
tz = timezone('Asia/Kuwait')
utc_dt = datetime.datetime.utcfromtimestamp(time.time())
utc_dt + tz.utcoffset(utc_dt)
>>> tz.utcoffset(utc_dt).seconds
10800
>>> tz
<DstTzInfo 'Asia/Kuwait' LMT+3:12:00 STD>
>>> utc_dt + tz.utcoffset(utc_dt)
datetime.datetime(2012, 10, 2, 17, 13, 53, 504322)
>>> utc_dt
datetime.datetime(2012, 10, 2, 14, 13, 53, 504322)
【讨论】:
tz.utcoffset()
将 utc_dt
解释为 tz
时区不正确的天真日期时间对象(utc_dt
是 UTC)。如果没有is_dst
参数,它也可能会产生 AmbiguousTimeError。【参考方案2】:
你可以使用pytz 和datetime 来做一些事情:
from datetime import datetime
from pytz import timezone
def get_diff(now, tzname):
tz = timezone(tzname)
utc = timezone('UTC')
utc.localize(datetime.now())
delta = utc.localize(now) - tz.localize(now)
return delta
下面的例子……
now = datetime.utcnow()
print(now)
tzname = 'Europe/Stockholm'
delta = get_diff(now, tzname)
print(delta)
now_in_stockholm = now + delta
print(now_in_stockholm)
...输出:
2012-10-02 14:38:56.547475
2:00:00
2012-10-02 16:38:56.547475
【讨论】:
【参考方案3】:假设“UTC 时间以秒为单位”表示 POSIX 时间戳。将其转换为斯德哥尔摩时间:
from datetime import datetime
import pytz
tz = pytz.timezone('Europe/Stockholm')
utc_dt = datetime.utcfromtimestamp(posix_timestamp).replace(tzinfo=pytz.utc)
dt = tz.normalize(utc_dt.astimezone(tz))
print(dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
如果源时区是 UTC(如本例中),则不需要tz.normalize()
。
更简单的替代方法是使用fromtimestamp()
的tz
参数,将“自纪元以来的秒数”转换为本地时间:
from datetime import datetime
import pytz
tz = pytz.timezone('Europe/Stockholm')
dt = datetime.fromtimestamp(posix_timestamp, tz)
print(dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
两个示例产生相同的结果。
如果本地机器使用“正确”的时区,然后将从外部源接收到的 POSIX 时间戳转换为 UTC,则可以使用明确的公式:
from datetime import datetime, timedelta
import pytz
utc_dt = datetime(1970, 1, 1, tzinfo=pytz.utc) + timedelta(seconds=posix_timestamp)
最新的公式还可能支持更大的日期范围(1970 年之前、2038 年或 3000 年之后的日期不太可能出现问题)。
如果时间戳来自本地“正确”来源,则应使用前两个示例(它们称为“正确”time.gmtime()
)。
【讨论】:
我喜欢这个,因为它看起来最接近我用labix.org/python-dateutil 拼凑的解决方案的样子。您如何看待 Kermit666 的回答? AmigableClarkKant:如果您需要偏移量:st_dt.utcoffset()
可能会起作用。无法评论@Kermit666 的回答:本地化时间的算术太复杂和错误。 乍一看它可能在前后和在 DST转换期间不起作用。
您更喜欢 pytz 而不是 python-dateutil 的任何特殊原因?出于某种原因(文档?)我发现 python-dateutil 更容易理解。 (或者更可能的是,相信,尽管 不正确,我理解。)
@AmigableClarkKant:I can't get it to work for times during DST。不代表dateutil
不行,可能我只是不知道怎么正确使用。
这是在我的书中坚持使用 pytz 的一个很好的理由,你是这样区分的人,一次又一次地指出 python 日期时间的陷阱。谢谢。【参考方案4】:
这已经很老了,但我找不到一个很好的答案,所以这是我想出的:
from datetime import datetime
local = datetime.now()
utc = datetime.utcnow()
int((local - utc).days * 86400 + round((local - utc).seconds, -1))
返回:
-21600
因为我(目前)落后 UTC 21600 秒(6 小时)。
注意:计算的第二个日期(在这种情况下为 UTC)需要四舍五入,因为每次计算的时间差异非常小。
【讨论】:
以上是关于从时区和 UTC 时间,获取该时间点与本地时间的秒差的主要内容,如果未能解决你的问题,请参考以下文章
Java 获取各时区时间,获取当前时间到格林威治时间1970年01月01日00时00分00秒的秒数