好的,首先让我说我的时区是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)
如上所述,这是错误的。
>>> 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)
现在它突然变得正确:/
我知道有几个问题已经存在,但给出的解决方案始终是“使用本地化”,但我的问题是LocalTimezone不提供该方法。
事实上,我有几个时间戳,以毫秒为单位,我需要本地时区的utcoffset(不仅是我的,而是使用该程序的任何人)。其中一个是我的时区中的1288483950000或2010年10月31日02:12:30 GMT + 0200(CEST)。
目前我执行以下操作来获取datetime对象:
datetime.datetime.fromtimestamp(int(int(millis)/1E3))
这将在几分钟内获得utcoffset:
-int(local_tnz.utcoffset(date).total_seconds()/60)
遗憾的是,在很多场合都错了:(。
有什么想法吗?
注意:我使用的是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)
local_tz等于tzlocal模块中的tzlocal.get_localzone()。
答案 0 :(得分:22)
根据Wikipedia,夏令时的转换发生在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中的模糊时间
您应该做的是为适当的时区构建 timezone 对象:
import pytz
cet = pytz.timezone('CET')
然后您可以使用 utcoffset 方法计算该时区中日期/时间的UTC偏移量。
dt = datetime.datetime(2010, 10, 31, 2, 12, 30)
offset = cet.utcoffset(dt)
请注意,上面的示例将抛出 AmbiguousTimeError 异常,因为它无法分辨出你的意思是02:12:30的两个版本中的哪一个。幸运的是,pytz将允许您通过设置 is_dst 参数来指定是否需要dst版本或标准版本。例如:
offset = cet.utcoffset(dt, is_dst = True)
请注意,对所有对 utcoffset 的调用设置此参数没有坏处,即使时间不明确也是如此。根据文档,它仅在DST过渡模糊期间用于解决这种模糊性。
如何处理时间戳
至于处理时间戳,最好尽可能长时间地将它们存储为UTC值,否则你最终可能会丢掉有价值的信息。因此,首先使用 datetime.utcfromtimestamp 方法转换为UTC日期时间。
dt = datetime.datetime.utcfromtimestamp(1288483950)
然后使用pytz将时间本地化为UTC,因此时区附加到日期时间对象。
dt = pytz.utc.localize(dt)
最后,您可以将UTC日期时间转换为您当地的时区,并获取如下所示的时区偏移量:
offset = dt.astimezone(cet).utcoffset()
请注意,这组计算将为1288483950和1288487550产生正确的偏移,即使两个时间戳都在CET时区的02:12:30表示。
确定当地时区
如果您需要使用计算机的本地时区而不是固定的时区,则无法直接从pytz执行此操作。您也不能使用 time.tzname 中的时区名称构建 pytz.timezone 对象,因为pytz不会始终识别名称。
解决方案是使用tzlocal module - 它的唯一目的是在pytz中提供这个缺少的功能。你这样使用它:
import tzlocal
local_tz = tzlocal.get_localzone()
get_localzone()函数返回 pytz.timezone 对象,因此您应该能够在我使用的所有地方使用该值上面例子中的cet 变量。
答案 1 :(得分:9)
给定一个以毫秒为单位的时间戳,您只需使用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)
如果我们忽略闰秒的时间,那么就没有模糊或不存在的时间。
如果操作系统维护历史时区数据库,它支持DST和utc偏移的更改,例如,它应该在Ubuntu上用于任何过去/现在的日期,但在Windows上可能会因使用不同的utc偏移的过去日期而中断。
使用适用于* nix和Win32系统的tzlocal
模块是一样的:
#!/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()
请参阅How to convert a python utc datetime to a local datetime using only python standard library?
以分钟为单位获取utc偏移量(Python 3.2 +):
from datetime import timedelta
minutes = utc_offset / timedelta(minutes=1)
请勿使用pytz.reference.LocalTimezone()
,it is only for tests。
答案 2 :(得分:0)
child: Text('Hello $_userName,'),
7200.0