如何获得系统时区设置并将其传递给pytz.timezone?

我们可以使用time.tzname获取当地的时区名称,但是这个名称与pytz.timezone不兼容。

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

  • 中部时区(北美) – 在北美中部时区观察到
  • 中国标准时间
  • 中原标准时间 – “春源标准时间”这个词在台湾很less使用
  • 澳大利亚中部标准时间(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 

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

即使本地时区的utc偏移量不同, local_tz也适用于过去的date。 基于dateutil.tz.tzlocal()的解决scheme在这种情况下失败,例如在欧洲/莫斯科时区(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()的问题仍然没有解决。 上面的例子现在可以工作,因为当前的utf偏移是在莫斯科的UTC + 3(意外等于1970年的utc偏移量)。 为了演示错误,我们可以select一个date,当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。

使用python-dateutil包中的tzlocal函数 :

 from dateutil.tz import tzlocal localtimezone = tzlocal() 

在内部,这是一个使用time.timezonetime.altzone (基于time.daylight切换)的类,但是time.daylight创build了一个合适的时区对象。

你用这个而不是 pytz时区。

另一种方法是从操作系统中读取当前configuration的时区,但这在OS和OS之间差别很大。 在Mac OS X上,您需要读取systemsetup -gettimezone的输出:

 $ systemsetup -gettimezone Time Zone: Europe/Copenhagen 

在Debian和Ubuntu系统上,你可以读取/etc/timezone

 $ cat /etc/timezone Europe/Oslo 

在RedHat和直接的系统上,您需要从/etc/sysconfig/clock读取它:

 $ grep ZONE /etc/sysconfig/clock ZONE="Europe/Oslo" 

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

 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 

我不知道这是否对你有用,但我认为它回答你的更一般的问题:

如果你有一个date模糊的时区,像CST , 简单的date (只有Python 3.2+,对不起)可以自动search,并允许你做喜欢某些国家的事情。

例如:

 >>> 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中对时区进行search来实现:

 >>> 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> 

给我的语言环境的时区(不明确或不)。