Python:找出当地时区

Ada*_*tan 55 python time timezone datetime utc

我想将日志文件中的UTC时间戳与本地时间戳进行比较.在创建本地datetime对象时,我使用如下内容:

>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0, 
                                 tzinfo=pytz.timezone('Israel'))
Run Code Online (Sandbox Code Playgroud)

我想找到一个自动工具来取代tzinfo=pytz.timezone('Israel')当前的本地时区.

有任何想法吗?

vbe*_*bem 73

在Python 3.x中,本地时区可能会像这样:

import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
Run Code Online (Sandbox Code Playgroud)

这是一个棘手datetime代码使用.

  • 这看起来不正确。如果我使用 `TZ=Australia/Sydney`,它会给出 `datetime.timezone(datetime.timedelta(seconds=36000), 'AEST')`。这是一个固定偏移时区,当应用于夏令时生效 6 个月后的日期时,它将给出错误的答案。 (12认同)
  • @Polv @sjngm并不像只适用于python> = 3.6.你不能在3.6之前的天真日期时间调用`astimezone()`. (8认同)
  • 只需`datetime.datetime.now()。astimezone()。tzinfo`就可以了。 (7认同)
  • @Polv`datetime.datetime.utcnow()。astimezone()。tzinfo`似乎也是正确的,并且对我来说更容易阅读,因为它明确指出要使用UTC作为开始。由于没有“ datetime”最初绑定到任何时区,因此在内部不应该有所作为。 (2认同)
  • 很聪明,但是如果您的程序长期运行(例如 DST 更改),它会起作用吗? (2认同)

Ste*_*ven 30

试试dateutil,它有一个tzlocal类型,可以满足你的需要.

  • 这不是一个非常标准的包...有更多的规范解决方案吗? (14认同)
  • 对于某些带有过去日期的时区,`dateutil`失败.对于它确实有效的情况,您可以使用[纯stdlib解决方案](http://stackoverflow.com/a/17363006/4279) (2认同)
  • 来自dateutil.tz import tzlocal (2认同)
  • @Jthorpe`dateutil`并不存在缺陷,并且正在积极开发中。 (2认同)

jfs*_*jfs 28

to compare UTC timestamps from a log file with local timestamps.

It is hard to find out Olson TZ name for a local timezone in a portable manner. Fortunately, you don't need it to perform the comparison.

tzlocal module returns a pytz timezone corresponding to the local timezone:

from datetime import datetime

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

tz = get_localzone()
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc) #NOTE: utc.normalize() is unnecessary here
Run Code Online (Sandbox Code Playgroud)

Unlike other solutions presented so far the above code avoids the following issues:

  • local time can be ambiguous i.e., a precise comparison might be impossible for some local times
  • utc offset can be different for the same local timezone name for dates in the past. Some libraries that support timezone-aware datetime objects (e.g., dateutil) fail to take that into account

Note: to get timezone-aware datetime object from a naive datetime object, you should use*:

local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
Run Code Online (Sandbox Code Playgroud)

instead of:

#XXX fails for some timezones
local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz)
Run Code Online (Sandbox Code Playgroud)

*is_dst=None forces an exception if given local time is ambiguous or non-existent.

If you are certain that all local timestamps use the same (current) utc offset for the local timezone then you could perform the comparison using only stdlib:

# convert a naive datetime object that represents time in local timezone to epoch time
timestamp1 = (datetime(2010, 4, 27, 12, 0, 0, 0) - datetime.fromtimestamp(0)).total_seconds()

# convert a naive datetime object that represents time in UTC to epoch time
timestamp2 = (datetime(2010, 4, 27, 9, 0) - datetime.utcfromtimestamp(0)).total_seconds()
Run Code Online (Sandbox Code Playgroud)

timestamp1 and timestamp2 can be compared directly.

Note:

  • timestamp1 formula works only if the UTC offset at epoch (datetime.fromtimestamp(0)) is the same as now
  • fromtimestamp() creates a naive datetime object in the current local timezone
  • utcfromtimestamp() creates a naive datetime object in UTC.

  • 我不明白为什么获取本地时区它不包含在Python核心模块之一中...... (4认同)
  • @Rfraile:如果我们排除需要“pytz”时区的极端情况,Python 就永远在 stdlib 中拥有本地时区。2- [PEP 615 - 标准库中对 IANA 时区数据库的支持](https://www.python.org/dev/peps/pep-0615/) 在 Python 3.9 中被接受(它提供了对与 `pytz` 相同的 tzdata) (3认同)
  • @jfs 我想说支持奥尔森时区,抱歉。很高兴知道这个新的 PEP 615,它将增加很大的价值,感谢分享 (2认同)

Dav*_*d L 14

我问自己一样,我在1中找到了答案:

看一下8.1.7节:格式"%z"(小写,Z大写也返回时区,但不是4位格式,但是以时区缩写的形式,如[3]中所示) strftime返回"+/- 4DIGIT"形式,这是电子邮件标题中的标准(参见RFC 2822的3.3节,参见[2],它废弃了指定电子邮件标题时区的其他方法).

因此,如果您想要这种格式的时区,请使用:

time.strftime("%z")
Run Code Online (Sandbox Code Playgroud)

[1] http://docs.python.org/2/library/datetime.html

[2] http://tools.ietf.org/html/rfc2822#section-3.3

[3]时区缩写:http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations,仅供参考.

  • 问题是找到对应于本地时区的`tzinfo`对象,而不是当前的utc offset作为字符串.[`time.timezone`,`.altzone`](http://stackoverflow.com/questions/13218506/how-to-get-system-timezone-setting-and-pass-it-to-pytz-timezone#comment25200533_13218990 )给你当前的utc偏移量.时区偏移或缩写是不明确的.获取本地时区并不容易,您可以在过去,现在和将来的日期使用这些时区.查看[`tzlocal`模块的源代码](https://github.com/regebro/tzlocal),看看如何完成它的示例. (2认同)

Rob*_*ews 7

以下似乎适用于 3.7+,使用标准库:

from datetime import timedelta
from datetime import timezone
import time

def currenttz():
    if time.daylight:
        return timezone(timedelta(seconds=-time.altzone),time.tzname[1])
    else:
        return timezone(timedelta(seconds=-time.timezone),time.tzname[0])
Run Code Online (Sandbox Code Playgroud)


hob*_*obs 7

要创建包含以色列当地时区的 ISO 表示形式的 ISO格式字符串( +04:00):

在以色列的服务器上:

>>> datetime.now(datetime.now().astimezone().tzinfo).isoformat()
'2021-09-07T01:02.030042+04:00'
Run Code Online (Sandbox Code Playgroud)

这将创建一个“时区感知”日期对象,该对象将与 UTC 或本地时间中的任何其他日期时间对象进行适当的比较。但是,如果您像我一样在同一时间在旧金山的服务器上运行它,则时区 ISO 表示(以及日期/时间字符串本身)将会改变:

在美国加利福尼亚州旧金山(太平洋)的服务器上:

>>> datetime.now(datetime.now().astimezone().tzinfo).isoformat()
'2021-09-06T14:01:02.030042-07:00'
Run Code Online (Sandbox Code Playgroud)

两种情况下的对象datetime都是相互兼容的。因此,如果减去它们,时间增量将为 0:

在 Python3.6+ 的任何服务器上:

>>> (datetime.fromisoformat('2021-09-06T14:01:02.030042-07:00') -
...  datetime.fromisoformat('2021-09-07T01:01:02.030042+04:00'))
datetime.timedelta(0)
Run Code Online (Sandbox Code Playgroud)


ami*_*lid 6

首先得到pytz和tzlocal模块

pip install pytz tzlocal
Run Code Online (Sandbox Code Playgroud)

然后

from tzlocal import get_localzone
local = get_localzone()
Run Code Online (Sandbox Code Playgroud)

然后你可以做的事情

from datetime import datetime
print(datetime.now(local))
Run Code Online (Sandbox Code Playgroud)


amo*_*hic 5

这是一种仅使用标准库获取本地时区的方法,(仅适用于 *nix 环境):

>>> '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
'Australia/Sydney'
Run Code Online (Sandbox Code Playgroud)

您可以使用它来创建pytz时区:

>>> import pytz
>>> my_tz_name = '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
>>> my_tz = pytz.timezone(my_tz_name)
>>> my_tz
<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>
Run Code Online (Sandbox Code Playgroud)

...然后您可以将其应用于 a datetime

>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059)

>>> now.replace(tzinfo=my_tz)
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059, tzinfo=<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>)
Run Code Online (Sandbox Code Playgroud)

  • 为了避免发明方轮,[查看 `tzlocal` 源代码](https://github.com/regebro/tzlocal) (4认同)
  • @Lucas,是的,确实如此,刚刚检查过,我使用的是 macOS Catalina 10.15.7 (2认同)

Dav*_*arx 5

这是@vbem 解决方案的更简洁版本:

from datetime import datetime as dt

dt.utcnow().astimezone().tzinfo
Run Code Online (Sandbox Code Playgroud)

唯一实质性的区别是我datetime.datetime.now(datetime.timezone.utc)datetime.datetime.utcnow(). 为简洁起见,我也别名datetime.datetimedt.

出于我的目的,我想要以秒为单位的 UTC 偏移量。这是它的样子:

dt.utcnow().astimezone().utcoffset().total_seconds()
Run Code Online (Sandbox Code Playgroud)

  • ValueError: astimezone() 不能应用于简单的日期时间(python 3.4) (2认同)