Python: Figure out local timezone
我想将日志文件中的UTC时间戳与本地时间戳进行比较。 在创建本地
1 2 | >>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=pytz.timezone('Israel')) |
我想找到一个自动工具,将
有任何想法吗?
在Python 3.x中,本地时区可能会像这样:
1 2 | import datetime LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo |
这是一个棘手的使用
试试dateutil,它有一个tzlocal类型,可以满足你的需要。
to compare UTC timestamps from a log file with local timestamps.
以便携方式很难找到本地时区的Olson TZ名称。幸运的是,您不需要它来执行比较。
1 2 3 4 5 6 7 8 | 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 |
与目前为止提供的其他解决方案不同,上述代码避免了以下问题:
- 当地时间可能不明确,即某些当地时间可能无法进行精确比较
-
对于过去日期的相同本地时区名称,utc offset可以不同。一些支持时区感知日期时间对象(例如,
dateutil )的库无法将其考虑在内
注意:要从天真的日期时间对象获取时区感知日期时间对象,您应该使用*:
1 | local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None) |
代替:
1 2 | #XXX fails for some timezones local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz) |
如果给定的本地时间不明确或不存在,*
如果您确定所有本地时间戳对本地时区使用相同(当前)的utc偏移量,那么您可以仅使用stdlib执行比较:
1 2 3 4 5 | # 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 公式仅在epoch(datetime.fromtimestamp(0) )的UTC偏移与现在相同时才有效 -
fromtimestamp() 在当前本地时区创建一个天真的日期时间对象 -
utcfromtimestamp() 以UTC格式创建一个天真的日期时间对象。
我问自己一样,我在1中找到了答案:
看一下8.1.7节:格式"%z"(小写,Z大写也返回时区,但不是4位格式,但是以时区缩写的形式,如[3]中所示) strftime返回"+/- 4DIGIT"形式,这是电子邮件标题中的标准(参见RFC 2822的3.3节,参见[2],它废弃了指定电子邮件标题时区的其他方法)。
因此,如果您想要这种格式的时区,请使用:
1 | 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模块
1 | pip install pytz tzlocal |
然后
1 2 | from tzlocal import get_localzone local = get_localzone() |
然后你可以做的事情
1 2 | from datetime import datetime print(datetime.now(local)) |
这是一种仅使用标准库获取本地时区的方法(仅适用于* nix环境):
1 2 | >>> '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:]) 'Australia/Sydney' |
您可以使用它来创建
1 2 3 4 5 | >>> 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> |
...然后您可以将其应用于
1 2 3 4 5 6 7 8 | >>> 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>) |
这是@ vbem解决方案的一个稍微简洁的版本:
1 2 3 | from datetime import datetime as dt dt.utcnow().astimezone().tzinfo |
唯一的实质区别是我用
就我的目的而言,我想要以秒为单位的UTC偏移量。 这是看起来像:
1 | dt.utcnow().astimezone().utcoffset().total_seconds() |
基于J. F. Sebastian的回答,您可以使用标准库执行此操作:
1 2 | import time, datetime local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone)) |
在3.4中测试,应该在3.4+上工作
基于Thoku的上述答案,这里的答案将时区解析为最近的半小时(这与某些时区相关,例如南澳大利亚州):
1 2 | from datetime import datetime round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2) |
避免使用非标准模块(似乎缺少日期时间模块的方法):
1 2 3 4 5 6 | 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) |
你可能会对钟摆感到满意
1 2 | >>> pendulum.datetime(2015, 2, 5, tz='local').timezone.name 'Israel' |
Pendulum有一个设计良好的API来操作日期。 一切都是TZ意识到的。
1 2 3 4 | now_dt = datetime.datetime.now() utc_now = datetime.datetime.utcnow() now_ts, utc_ts = map(time.mktime, map(datetime.datetime.timetuple, (now_dt, utc_now))) offset = int((now_ts - utc_ts) / 3600) |
希望这会帮助你。
对于简单的事情,可以使用以下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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()) |
首先,请注意该问题表示感知日期时间对象的初始化不正确:
1 2 | >>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0, ... tzinfo=pytz.timezone('Israel')) |
创建一个无效的实例。可以通过计算结果对象的UTC偏移量来查看问题:
1 2 | >>> print(local_time.utcoffset()) 2:21:00 |
(注意结果是一小时的奇怪部分。)
要使用pytz正确初始化感知日期时间,应使用
1 2 3 | >>> 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进行调整,你可以调用没有参数的
1 2 | >>> local_time.astimezone().strftime('%Y-%m-%d %H:%M %Z %z') '2010-04-27 05:00 EDT -0400' |
来自dateutil的tzlocal。
代码示例如下。最后一个字符串适用于文件名。
1 2 3 4 5 6 7 | >>> 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' >>> |