我想要比较日志文件中的UTC时间戳和本地时间戳。当创建本地datetime
对象时,我使用类似以下的代码:
>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
tzinfo=pytz.timezone('Israel'))
我想找一个自动工具,可以将tzinfo=pytz.timezone('Israel')
替换为当前的本地时区。
有什么建议吗?
在Python 3.x中,可以通过以下方式确定本地时区:
>>> import datetime
>>> print(datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo)
AEST
这是datetime
的一个棘手用法代码。
对于Python版本小于3.6的情况,您需要
>>> import datetime
>>> print(datetime.datetime.now(datetime.timezone(datetime.timedelta(0))).astimezone().tzinfo)
AEST
datetime.datetime.now().astimezone().tzinfo
即可。 - Polvdatetime.datetime.utcnow().astimezone().tzinfo
似乎也是正确的,对我来说更易于阅读,因为它明确表示它首先将使用UTC。由于没有任何时区最初绑定到任何 datetime
,所以在内部不应该有任何区别。 - sjngmastimezone()
方法。 - Fynn BeckerTZ=Australia/Sydney
,它会给出datetime.timezone(datetime.timedelta(seconds=36000), 'AEST')
。 这是一个固定偏移的时区,在应用于夏令时生效的日期六个月后将会得到错误的答案。 - James Henstridgefrom dateutil.tz import tzlocal
- Andy Haydendateutil
并未过时,而且正在积极开发中。 - tacaswell比较日志文件中的UTC时间戳与本地时间戳。
以便于移植的方式很难找到本地时区的Olson TZ名称。幸运的是,您不需要它来执行比较。
tzlocal
模块返回对应于本地时区的pytz时区:
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
与迄今为止提出的其他解决方案不同,上述代码避免了以下问题:
dateutil
)的库未能考虑到这一点注意:要从naive datetime获得时区感知datetime对象,应使用*:
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
#XXX fails for some timezones
local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz)
*is_dst=None
会在给定的当地时间存在歧义或不存在时引发异常。
如果你确定所有本地时间戳使用相同的(当前的)utc偏移量作为本地时区,那么你可以仅使用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()
timestamp1
和timestamp2
可以直接比较。
注意:
timestamp1
公式仅在纪元时的UTC偏移量(datetime.fromtimestamp(0)
)与当前时间相同时有效。fromtimestamp()
会创建一个本地时区的无时区信息datetime对象。utcfromtimestamp()
会创建一个UTC的无时区信息datetime对象。pytz
时区的特殊情况,Python自始至终都有标准库中的本地时区。Python 3.9已经接受了PEP 615 -- 支持IANA时区数据库的标准库(它提供了与pytz
相同的tzdata访问)。 - jfstime.strftime("%z")
[1] http://docs.python.org/2/library/datetime.html
[2] https://www.rfc-editor.org/rfc/rfc2822#section-3.3
[3] 时区缩写:http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations,仅供参考。
tzinfo
对象,而不是当前UTC偏移量作为字符串。[time.timezone
, .altzone
](https://dev59.com/u2Ys5IYBdhLWcg3wAfLO#comment25200533_13218990)可以给出当前的UTC偏移量。时区偏移或缩写是有歧义的。获取可用于过去、现在和未来日期的本地时区并不容易。查看[`tzlocal`模块的源代码](https://github.com/regebro/tzlocal),以了解如何实现此功能的示例。 - jfs以下似乎适用于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])
首先获取pytz和tzlocal模块
pip install pytz tzlocal
那么
from tzlocal import get_localzone
local = get_localzone()
那么您可以做诸如以下的事情:
from datetime import datetime
print(datetime.now(local))
>>> datetime.now(datetime.now().astimezone().tzinfo).isoformat()
'2021-09-07T01:02.030042+04:00'
这将创建一个“时区感知”的日期对象,可以与任何其他UTC或本地时间的日期时间对象进行比较。但是,如果您在旧金山的服务器上在完全相同的时间运行此代码,则ISO表示(以及日期/时间字符串本身)将会改变:
>>> datetime.now(datetime.now().astimezone().tzinfo).isoformat()
'2021-09-06T14:01:02.030042-07:00'
在这两种情况下,datetime
对象都是相互兼容的。因此,如果你对它们进行减法运算,你将得到一个时间差为0:
>>> (datetime.fromisoformat('2021-09-06T14:01:02.030042-07:00') -
... datetime.fromisoformat('2021-09-07T01:01:02.030042+04:00'))
datetime.timedelta(0)
from datetime import datetime as dt
dt.utcnow().astimezone().tzinfo
唯一实质性的区别是我将datetime.datetime.now(datetime.timezone.utc)
替换为datetime.datetime.utcnow()
。为了简洁起见,我还将datetime.datetime
别名为dt
。
就我的目的而言,我想要以秒为单位的UTC偏移量。如下所示:
dt.utcnow().astimezone().utcoffset().total_seconds()
pytz
和tzlocal
。当Python已经内置了这么多功能时,我对添加第三方依赖库持谨慎态度,但是在处理时区时,显然需要外部帮助。 - pbarill以下是一种仅使用标准库获取本地时区的方法(仅适用于*nix环境):
>>> '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
'Australia/Sydney'
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>
你可以将这些模式应用于 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>)
避免非标准模块(似乎是datetime模块缺少的方法):
from datetime import datetime
utcOffset_min = int(round((datetime.now() - datetime.utcnow()).total_seconds())) / 60 # round for taking time twice
utcOffset_h = utcOffset_min / 60
assert(utcOffset_min == utcOffset_h * 60) # we do not handle 1/2 h timezone offsets
print 'Local time offset is %i h to UTC.' % (utcOffset_h)
-time.timezone
。 - jfs
local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0).astimezone()
(Python >= 3.6)这样的带有时区信息的日期时间对象来获取它。[文档] - FObersteiner