Jor*_*ren 18 python timezone pytz timezone-offset
好吧,首先让我说我的时区是CET/CEST.它从CEST变为CET的确切时刻(从DST返回,即GMT + 2,再到正常,GMT + 1,因此)始终是10月的最后一个星期日凌晨3点.2010年10月31日凌晨3点.
现在请注意以下事项:
>>> import datetime
>>> import pytz.reference
>>> local_tnz = pytz.reference.LocalTimezone()
>>> local_tnz.utcoffset(datetime.datetime(2010, 10, 31, 2, 12, 30))
datetime.timedelta(0, 3600)
Run Code Online (Sandbox Code Playgroud)
如上所述,这是错误的.
>>> local_tnz.utcoffset(datetime.datetime(2010, 10, 30, 2, 12, 30))
datetime.timedelta(0, 7200)
>>> local_tnz.utcoffset(datetime.datetime(2010, 10, 31, 2, 12, 30))
datetime.timedelta(0, 7200)
Run Code Online (Sandbox Code Playgroud)
现在它突然变得正确:/
我知道有几个问题已经存在,但给出的解决方案始终是"使用本地化",但我的问题是LocalTimezone不提供该方法.
事实上,我有几个时间戳,以毫秒为单位,我需要本地时区的utcoffset(不仅是我的,而是使用该程序的任何人).其中一个是1288483950000或Sun Oct 31 2010 02:12:30 GMT + 0200(CEST)在我的时区.
目前我执行以下操作来获取datetime对象:
datetime.datetime.fromtimestamp(int(int(millis)/1E3))
Run Code Online (Sandbox Code Playgroud)
这将在几分钟内得到utcoffset:
-int(local_tnz.utcoffset(date).total_seconds()/60)
Run Code Online (Sandbox Code Playgroud)
不幸的是,在很多场合都是错的:(.
有任何想法吗?
注意:我正在使用python3.2.4,而不是在这种情况下它应该是重要的.
编辑:
通过@JamesHolderness找到解决方案:
def datetimeFromMillis(millis):
return pytz.utc.localize(datetime.datetime.utcfromtimestamp(int(int(millis)/1E3)))
def getTimezoneOffset(date):
return -int(date.astimezone(local_tz).utcoffset().total_seconds()/60)
Run Code Online (Sandbox Code Playgroud)
local_tz等于tzlocal模块中的tzlocal.get_localzone().
Jam*_*ess 27
根据维基百科,夏季时间的转换发生在UTC时间01:00.
在UTC时间00:12,您仍然处于中欧夏令时(即UTC + 02:00),因此当地时间是02:12.
在UTC时间01:12您回到标准的中欧时间(即UTC + 01:00),所以当地时间再次是02:12.
当从夏令时回到标准时间时,当地时间从02:59回到02:00,小时重复.因此,当要求UTC偏移02:12(当地时间)时,答案可能是+01:00或+02:00 - 这取决于您所说的是哪个版本的02:12.
关于pytz库的进一步研究,我认为你的问题可能是你不应该使用pytz.reference实现,这可能不能很好地处理这些歧义.引自源代码中的注释:
参考Python文档中的tzinfo实现.用于测试,因为它们仅适用于1987年至2006年.不要将它们用于实际代码.
在pytz中处理模棱两可的时间
你应该做的是为适当的时区构建一个时区对象:
import pytz
cet = pytz.timezone('CET')
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用utcoffset方法计算该时区中日期/时间的UTC偏移量.
dt = datetime.datetime(2010, 10, 31, 2, 12, 30)
offset = cet.utcoffset(dt)
Run Code Online (Sandbox Code Playgroud)
注意,上面的例子会抛出一个AmbiguousTimeError异常,因为它无法分辨你的两个版本02:12:30中的哪一个.幸运的是,pytz允许您通过设置is_dst参数来指定是否需要dst版本或标准版本.例如:
offset = cet.utcoffset(dt, is_dst = True)
Run Code Online (Sandbox Code Playgroud)
请注意,对所有对utcoffset的调用设置此参数没有坏处,即使时间不明确也是如此.根据文档,它仅在DST过渡模糊期间用于解决这种模糊性.
如何处理时间戳
至于处理时间戳,最好尽可能长时间地将它们存储为UTC值,否则你最终会丢掉有价值的信息.因此,首先使用datetime.utcfromtimestamp方法转换为UTC日期时间.
dt = datetime.datetime.utcfromtimestamp(1288483950)
Run Code Online (Sandbox Code Playgroud)
然后使用pytz将时间本地化为UTC,因此时区附加到datetime对象.
dt = pytz.utc.localize(dt)
Run Code Online (Sandbox Code Playgroud)
最后,您可以将UTC日期时间转换为您当地的时区,并获取如下所示的时区偏移量:
offset = dt.astimezone(cet).utcoffset()
Run Code Online (Sandbox Code Playgroud)
请注意,这组计算将为1288483950和1288487550生成正确的偏移量,即使两个时间戳都在CET时区的02:12:30表示.
确定当地时区
如果您需要使用计算机的本地时区而不是固定时区,则不能直接从pytz执行此操作.您也不能使用time.tzname中的时区名称构造pytz.timezone对象,因为pytz不会始终识别名称.
解决方案是使用tzlocal模块 - 它的唯一目的是在pytz中提供这个缺少的功能.你这样使用它:
import tzlocal
local_tz = tzlocal.get_localzone()
Run Code Online (Sandbox Code Playgroud)
该get_localzone()函数返回一个pytz.timezone对象,所以你应该能够使用该值在我使用的所有地方CET变量在上面的例子.
jfs*_*jfs 10
给定一个以毫秒为单位的时间戳,您只需使用stdlib即可获得本地时区的utc偏移量:
#!/usr/bin/env python
from datetime import datetime
millis = 1288483950000
ts = millis * 1e-3
# local time == (utc time + utc offset)
utc_offset = datetime.fromtimestamp(ts) - datetime.utcfromtimestamp(ts)
Run Code Online (Sandbox Code Playgroud)
如果我们忽略闰秒的时间,则没有模糊或不存在的时间.
如果操作系统维护历史时区数据库,它支持DST和utc偏移的更改,例如,它应该在Ubuntu上用于任何过去/现在的日期,但在Windows上可能会在过去使用不同utc偏移的日期中断.
这里使用的tzlocal模块应该适用于*nix和Win32系统:
#!/usr/bin/env python
from datetime import datetime
from tzlocal import get_localzone # pip install tzlocal
millis = 1288483950000
ts = millis * 1e-3
local_dt = datetime.fromtimestamp(ts, get_localzone())
utc_offset = local_dt.utcoffset()
Run Code Online (Sandbox Code Playgroud)
请参阅如何仅使用python标准库将python utc datetime转换为本地日期时间?
要在几分钟内获得utc偏移量(Python 3.2+):
from datetime import timedelta
minutes = utc_offset / timedelta(minutes=1)
Run Code Online (Sandbox Code Playgroud)
不要使用pytz.reference.LocalTimezone(),它仅用于测试.