71

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

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

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

6 回答 6

83

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()来说仍然是破碎的。上面的例子现在可以工作了,因为莫斯科的当前 utf 偏移量是 UTC+3(偶然等于 1970 年的 utc 偏移量)。为了演示错误,我们可以选择 UTC 偏移量为 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 年 6 月 1 日返回错误的 UTC+3 偏移量,而不是正确的 UTC+4。

于 2013-06-28T13:26:26.900 回答
38

使用中的tzlocal函数python-dateutil

from dateutil.tz import tzlocal

localtimezone = tzlocal()

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

您使用它而不是pytz区。

另一种方法是从操作系统读取当前配置的时区,但这因操作系统而异。在 Mac OS X 上,您需要阅读以下输出systemsetup -gettimezone

$ systemsetup -gettimezone
Time Zone: Europe/Copenhagen

在 Debian 和 Ubuntu 系统上,您可以阅读/etc/timezone

$ cat /etc/timezone
Europe/Oslo

在 RedHat 和 direved 系统上,您需要从以下位置读取它/etc/sysconfig/clock

$ grep ZONE /etc/sysconfig/clock
ZONE="Europe/Oslo"
于 2012-11-04T12:30:29.720 回答
31

从 Python 3.6 开始,您可以简单地运行naive_datetime.astimezone()并将系统时区添加到naive_datetime对象中。

如果不带参数调用(或使用 tz=None),则系统本地时区假定为目标时区。转换后的日期时间实例的 .tzinfo 属性将设置为时区实例,其区域名称和偏移量从操作系统获得。

https://docs.python.org/3/library/datetime.html#datetime.datetime.astimezone

例子:

>>> import datetime
>>> datetime.datetime.now().astimezone().isoformat(timespec='minutes')
'2018-10-02T13:09+03:00'
于 2018-10-02T10:20:13.067 回答
9

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

import time

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

更新:@MartijnPieters 说“这不适用于 DST / 夏季。” 那么这个版本呢?

import time

def localTzname():
    if time.daylight:
        offsetHour = time.altzone / 3600
    else:
        offsetHour = time.timezone / 3600
    return 'Etc/GMT%+d' % offsetHour
于 2012-11-04T13:35:07.207 回答
1

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

如果您的日期在不明确的时区中,例如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>

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

于 2013-07-04T23:18:40.553 回答
-5
import pytz

假设您在 OBJ 列表对象中有 utc DateTime 值列表。

tz=pytz.timezone('Asia/Singapore')

在下面找到 url 以获取相应的时区位置字符串参数 是否有 Pytz 时区列表?

现在我们的 tz 是具有新加坡时间的对象

result=[]
for i in OBJ:
    i=i+tz.utcoffset(i)
    result.append(i)

结果列表对象具有您各自时区的 DateTime 值

于 2018-09-26T09:07:11.763 回答