Python:找出当地的时区

我想比较一个日志文件的UTC时间戳与本地时间戳。 在创build本地datetime对象时,我使用了如下的东西:

 >>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=pytz.timezone('Israel')) 

我想find一个自动工具,用当前的本地时区replacetzinfo=pytz.timezone('Israel')

有任何想法吗?

尝试dateutil ,它有一个tzlocaltypes,做你所需要的。

比较来自日志文件的UTC时间戳与本地时间戳。

以便携的方式很难find当地时区的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 

与迄今为止提出的其他解决scheme不同,上述代码避免了以下问题:

  • 当地时间可能是模棱两可的,即当地一些时期可能无法进行精确比较
  • 对于过去的date,相同的本地时区名称的utc偏移量可能不同。 一些支持时区感知的date时间对象的库(如dateutil )没有考虑到这一点

注意:为了从天真的date时间对象中获得时区感知的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如果给定本地时间不明确或不存在,则强制exception。

如果您确定所有本地时间戳使用当地时区的相同(当前)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() 

timestamp1timestamp2可以直接比较。

注意:

  • timestamp1公式只在时期( datetime.fromtimestamp(0) )的UTC偏移与现在相同时才起作用
  • fromtimestamp()在当前本地时区中创build一个天真的date时间对象
  • utcfromtimestamp()在UTC中创build一个天真的date时间对象。

在Python 3.x中,本地时区可以这样算出来:

 import datetime LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo 

这是datetime的代码的一个棘手的使用。

我对自己也是这样问的,我在1:

看一下8.1.7节:格式“%z”(小写字母,Z大写字母还返回时区,但不是以4位格式,而是以时区缩写的forms,如[3])。 of strftime返回电子邮件标题中的标准forms“+/- 4DIGIT”(请参阅​​RFC 2822的第3.3节,参见[2],该过程废止了为电子邮件标题指定时区的其他方式)。

所以,如果你想要这种格式的时区,使用:

 time.strftime("%z") 

[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 ,仅供参考。

首先得到pytz和tzlocal模块

点安装pytz tzlocal

然后

 from tzlocal import get_localzone local = get_localzone() 

那么你可以做类似的事情

 from datetime import datetime print(datetime.now(local)) 

避免非标准模块(似乎是一个缺lessdatetime模块的方法):

 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 %ih to UTC.' % (utcOffset_h) 

根据上面的Thoku的答案,这里是一个答案,将时区解决到最近的半小时(这与某些时区如南澳大利亚州有关):

 from datetime import datetime round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2) 

下面是一个只使用标准库来获取本地时区的方法(仅适用于* nix环境):

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

你可以用这个来创build一个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>) 

基于JF Sebastian的回答 ,你可以用标准库来做到这一点:

 import time, datetime local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone)) 

在3.4testing,应该工作在3.4+

对于简单的事情,可以使用下面的tzinfo实现,它向操作系统查询时区偏移:

 import datetime import time class LocalTZ(datetime.tzinfo): _unixEpochOrdinal = datetime.datetime.utcfromtimestamp(0).toordinal() def dst(self, dt): return datetime.timedelta(0) def utcoffset(self, dt): t = (dt.toordinal() - self._unixEpochOrdinal)*86400 + dt.hour*3600 + dt.minute*60 + dt.second + time.timezone utc = datetime.datetime(*time.gmtime(t)[:6]) local = datetime.datetime(*time.localtime(t)[:6]) return local - utc print datetime.datetime.now(LocalTZ()) print datetime.datetime(2010, 4, 27, 12, 0, 0, tzinfo=LocalTZ()) # If you're in the EU, the following datetimes are right on the DST change. print datetime.datetime(2013, 3, 31, 0, 59, 59, tzinfo=LocalTZ()) print datetime.datetime(2013, 3, 31, 1, 0, 0, tzinfo=LocalTZ()) print datetime.datetime(2013, 3, 31, 1, 59, 59, tzinfo=LocalTZ()) # The following datetime is invalid, as the clock moves directly from # 01:59:59 standard time to 03:00:00 daylight savings time. print datetime.datetime(2013, 3, 31, 2, 0, 0, tzinfo=LocalTZ()) print datetime.datetime(2013, 10, 27, 0, 59, 59, tzinfo=LocalTZ()) print datetime.datetime(2013, 10, 27, 1, 0, 0, tzinfo=LocalTZ()) print datetime.datetime(2013, 10, 27, 1, 59, 59, tzinfo=LocalTZ()) # The following datetime is ambigous, as 02:00 can be either DST or standard # time. (It is interpreted as standard time.) print datetime.datetime(2013, 10, 27, 2, 0, 0, tzinfo=LocalTZ()) 

首先,请注意,该问题提供了一个意识到的date时间对象的不正确的初始化:

 >>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0, ... tzinfo=pytz.timezone('Israel')) 

创build一个无效的实例。 通过计算结果对象的UTC偏移量,可以看到问题:

 >>> print(local_time.utcoffset()) 2:21:00 

(注意结果是一个小时的奇数部分)

要使用pytz正确初始化一个知晓的date时间,应该使用localize()方法如下:

 >>> local_time=pytz.timezone('Israel').localize(datetime.datetime(2010, 4, 27, 12)) >>> print(local_time.utcoffset()) 3:00:00 

现在,如果你需要一个本地pytz时区作为新的tzinfo,你应该像其他人所说的那样使用tzlocal包,但是如果你只需要一个带有正确的本地时区偏移和缩写的实例,那么你可以用Python 3.3调用不带任何参数的astimezone()方法来将感知的datetime实例转换为本地时区:

 >>> local_time.astimezone().strftime('%Y-%m-%d %H:%M %Z %z') '2010-04-27 05:00 EDT -0400' 

从dateutil tzlocal 。

代码示例如下。 最后一个string适用于文件名。

 >>> from datetime import datetime >>> from dateutil.tz import tzlocal >>> str(datetime.now(tzlocal())) '2015-04-01 11:19:47.980883-07:00' >>> str(datetime.now(tzlocal())).replace(' ','-').replace(':','').replace('.','-') '2015-04-01-111947-981879-0700' >>>