python - pytz北京时间 - time mktime时区




如何获取系统时区设置并将其传递给pytz.timezone? (3)

我们可以使用time.tzname获取本地时区名称,但该名称与pytz.timezone不兼容。

实际上, time.tzname返回的名称是不明确的。 此方法在我的系统中返回('CST', 'CST') ,但'CST'可以指示四个时区:

  • 中部时区(北美) - 在北美的中部时区观察
  • 中国标准时间
  • 中原标准时间 - “中原标准时间”一词现在在台湾很少使用
  • 澳大利亚中央标准时间(ACST)

tzlocal模块返回对应于本地时区的pytz tzinfo对象:

import time
from datetime import datetime

import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal

# get local timezone    
local_tz = get_localzone() 

# test it
# utc_now, now = datetime.utcnow(), datetime.now()
ts = time.time()
utc_now, now = datetime.utcfromtimestamp(ts), datetime.fromtimestamp(ts)

local_now = utc_now.replace(tzinfo=pytz.utc).astimezone(local_tz) # utc -> local
assert local_now.replace(tzinfo=None) == now

即使在夏令时转换期间,当本地时间可能不明确时,它也能工作。

local_tz也适用于过去的日期,即使当地时区的utc偏移量当时不同。 基于dateutil.tz.tzlocal()的解决方案在这种情况下失败,例如,在欧洲/莫斯科时区(2013年的例子):

>>> import os, time
>>> os.environ['TZ'] = 'Europe/Moscow'
>>> time.tzset()
>>> from datetime import datetime
>>> from dateutil.tz import tzlocal
>>> from tzlocal import get_localzone
>>> dateutil_tz = tzlocal()
>>> tzlocal_tz = get_localzone()
>>> datetime.fromtimestamp(0, dateutil_tz)                              
datetime.datetime(1970, 1, 1, 4, 0, tzinfo=tzlocal())
>>> datetime.fromtimestamp(0, tzlocal_tz)
datetime.datetime(1970, 1, 1, 3, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+3:00:00 STD>)

dateutil在1970-01-01上返回错误的 UTC + 4偏移而不是正确的UTC + 3。

对于那些在2017年 dateutil.tz.tzlocal() 这种情况的人来说, dateutil.tz.tzlocal()仍然被打破。 上面的例子现在起作用了,因为莫斯科当前的utf偏移量是UTC + 3(偶然等于1970年的utc偏移量)。 为了演示错误,我们可以选择utc offset为UTC + 4时的日期:

>>> import os, time
>>> os.environ['TZ'] = 'Europe/Moscow'
>>> time.tzset()
>>> from datetime import datetime
>>> from dateutil.tz import tzlocal
>>> from tzlocal import get_localzone
>>> dateutil_tz = tzlocal()
>>> tzlocal_tz = get_localzone()
>>> ts = datetime(2014, 6,1).timestamp() # get date in 2014 when gmtoff=14400 in Moscow
>>> datetime.fromtimestamp(ts, dateutil_tz)
datetime.datetime(2014, 5, 31, 23, 0, tzinfo=tzlocal())
>>> datetime.fromtimestamp(ts, tzlocal_tz)
datetime.datetime(2014, 6, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+4:00:00 STD>)

dateutil在2014-06-01上返回错误的 UTC + 3偏移而不是正确的UTC + 4。


一个非常简单的方法来解决这个问题:

import time

def localTzname():
    offsetHour = time.timezone / 3600
    return 'Etc/GMT%+d' % offsetHour

更新 :@MartijnPieters说'这不适用于夏令时/夏季。' 那这个版本怎么样?

import time

def localTzname():
    if time.daylight:
        offsetHour = time.altzone / 3600
    else:
        offsetHour = time.timezone / 3600
    return 'Etc/GMT%+d' % offsetHour

我不知道这对你有用,但我认为它可以解决你更普遍的问题:

如果您的日期位于模糊时区(如CSTsimple-date (仅限python 3.2+,抱歉)可以自动执行搜索,并允许您执行喜欢某些国家/地区的操作。

例如:

>>> SimpleDate('2013-07-04 18:53 CST')
Traceback [...
simpledate.AmbiguousTimezone: 3 distinct timezones found: <DstTzInfo 'Australia/Broken_Hill' CST+9:30:00 STD>; <DstTzInfo 'America/Regina' LMT-1 day, 17:01:00 STD>; <DstTzInfo 'Asia/Harbin' LMT+8:27:00 STD> (timezones=('CST',), datetime=datetime.datetime(2013, 7, 4, 18, 53), is_dst=False, country=None, unsafe=False)
>>> SimpleDate('2013-07-04 18:53 CST', country='CN')
SimpleDate('2013-07-04 18:53 CST')
>>> SimpleDate('2013-07-04 18:53 CST', country='CN').utc
SimpleDate('2013-07-04 10:53 UTC', tz='UTC')

请注意,通过指定国家/地区,您可以充分减少可能值的范围以允许转换为UTC。

它是通过在PyTZ中搜索时区来实现的:

>>> SimpleDate('2013-07-04 18:53 CST', country='CN', debug=True)
...
PyTzFactory: Have country code CN
PyTzFactory: Country code CN has 5 timezones
PyTzFactory: Expanded country codes to 5 timezones
PyTzFactory: Expanding ('CST',)
PyTzFactory: Name lookup failed for CST
PyTzFactory: Found CST using Asia/Shanghai
PyTzFactory: Found CST using Asia/Harbin
PyTzFactory: Found CST using Asia/Chongqing
PyTzFactory: Found CST using Asia/Urumqi
PyTzFactory: Found CST using Asia/Kashgar
PyTzFactory: Expanded timezone to 5 timezones
PyTzFactory: New offset 8:00:00 for Asia/Shanghai
PyTzFactory: Known offset 8:00:00 for Asia/Harbin
PyTzFactory: Known offset 8:00:00 for Asia/Chongqing
PyTzFactory: Known offset 8:00:00 for Asia/Urumqi
PyTzFactory: Known offset 8:00:00 for Asia/Kashgar
PyTzFactory: Have 1 distinct timezone(s)
PyTzFactory: Found Asia/Shanghai
...
SimpleDate('2013-07-04 18:53 CST')

最后,为了回答直接提出的问题,它还包含了tzlocal,正如在另一个答案中所提到的那样,如果你没有给出时区,它会自动完成你所期望的。 例如,我住在智利,所以

>>> SimpleDate()
SimpleDate('2013-07-04 19:21:25.757222 CLT', tz='America/Santiago')
>>> SimpleDate().tzinfo
<DstTzInfo 'America/Santiago' CLT-1 day, 20:00:00 STD>

给出我的语言环境的时区(模糊或不模糊)。





pytz