ISO time (ISO 8601) in Python
我有一个文件。 在Python中,我想花费它的创建时间,并将其转换为ISO时间(ISO 8601)字符串,同时保留它在东部时区(ET)中创建的事实。
如何获取文件的ctime并将其转换为指示东部时区的ISO时间字符串(并在必要时考虑夏令时)?
ISO  8601的本地:
1 2 | import datetime datetime.datetime.now().isoformat() |
UTC到ISO  8601:
1 2 | import datetime datetime.datetime.utcnow().isoformat() |
本地到ISO  8601没有微秒:
1 2 | import datetime datetime.datetime.now().replace(microsecond=0).isoformat() |
带有TimeZone信息的UTC到ISO  8601(Python  3):
1 2 | import datetime datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).isoformat() |
带有TimeZone信息的ISO  8601本地化(Python  3):
1 2 3 4 5 6 | import datetime, time # Calculate the offset taking into account daylight saving time utc_offset_sec = time.altzone if time.localtime().tm_isdst else time.timezone utc_offset = datetime.timedelta(seconds=-utc_offset_sec) datetime.datetime.now().replace(tzinfo=datetime.timezone(offset=utc_offset)).isoformat() |
对于Python 2,请参阅并使用pytz。
这是我用来转换为XSD日期时间格式的内容:
1 2 3 | from datetime import datetime datetime.now().replace(microsecond=0).isoformat() # You get your ISO string |
在查找XSD日期时间格式(
我在文档中找到了datetime.isoformat。它似乎做你想要的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | datetime.isoformat([sep]) Return a string representing the date and time in ISO 8601 format, YYYY-MM-DDTHH:MM:SS.mmmmmm or, if microsecond is 0, YYYY-MM-DDTHH:MM:SS If utcoffset() does not return None, a 6-character string is appended, giving the UTC offset in (signed) hours and minutes: YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or, if microsecond is 0 YYYY-MM-DDTHH:MM:SS+HH:MM The optional argument sep (default 'T') is a one-character separator, placed between the date and time portions of the result. For example, >>> >>> from datetime import tzinfo, timedelta, datetime >>> class TZ(tzinfo): ... def utcoffset(self, dt): return timedelta(minutes=-399) ... >>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ') '2002-12-25 00:00:00-06:39' |
ISO 8601时间表示
国际标准ISO 8601描述了日期和时间的字符串表示。这种格式的两个简单例子是
1 2 | 2010-12-16 17:22:15 20101216T172215 |
(两者均代表2010年12月16日),但格式也允许亚秒级分辨率时间并指定时区。这种格式当然不是特定于Python的,但它适合以便携式格式存储日期和时间。有关此格式的详细信息,请参阅Markus Kuhn条目。
我建议使用此格式在文件中存储时间。
在此表示中获取当前时间的一种方法是使用Python标准库中time模块的strftime:
1 2 3 | >>> from time import strftime >>> strftime("%Y-%m-%d %H:%M:%S") '2010-03-03 21:16:45' |
您可以使用datetime类的strptime构造函数:
1 2 3 | >>> from datetime import datetime >>> datetime.strptime("2010-06-04 21:08:12","%Y-%m-%d %H:%M:%S") datetime.datetime(2010, 6, 4, 21, 8, 12) |
最强大的是Egenix mxDateTime模块:
1 2 3 4 5 | >>> from mx.DateTime.ISO import ParseDateTimeUTC >>> from datetime import datetime >>> x = ParseDateTimeUTC("2010-06-04 21:08:12") >>> datetime.fromtimestamp(x) datetime.datetime(2010, 3, 6, 21, 8, 12) |
参考
-
Python时间模块文档
-
Python datetime类文档
-
Egenix mxDateTime类
ISO 8601时间格式不存储时区名称,仅保留相应的UTC偏移。
要将文件ctime转换为ISO  8601时间字符串,同时在Python中保留UTC偏移量  3:
1 2 3 4 5 6 | >>> import os >>> from datetime import datetime, timezone >>> ts = os.path.getctime(some_file) >>> dt = datetime.fromtimestamp(ts, timezone.utc) >>> dt.astimezone().isoformat() '2015-11-27T00:29:06.839600-05:00' |
该代码假定您的本地时区是东部时区(ET),并且您的系统为给定的POSIX时间戳(
如果您需要便携式解决方案;使用提供对tz数据库的访问的
1 2 3 4 5 6 7 | >>> import os >>> from datetime import datetime >>> import pytz # pip install pytz >>> ts = os.path.getctime(some_file) >>> dt = datetime.fromtimestamp(ts, pytz.timezone('America/New_York')) >>> dt.isoformat() '2015-11-27T00:29:06.839600-05:00' |
在这种情况下结果是相同的。
如果您需要时区名称/缩写/区域ID,请单独存储。
1 2 | >>> dt.astimezone().strftime('%Y-%m-%d %H:%M:%S%z (%Z)') '2015-11-27 00:29:06-0500 (EST)' |
注意:不,UTC偏移中的
同一库的不同库/不同版本可以对同一日期/时区使用不同的时区规则。如果是未来日期,则规则可能尚未知晓。换句话说,相同的UTC时间可能对应于不同的本地时间,具体取决于您使用的规则 - 以ISO  8601格式保存时间可保留UTC时间以及与您当前使用的当前时区规则相对应的当地时间平台。如果具有不同的规则,您可能需要在不同的平台上重新计算本地时间。
您需要使用
1 2 3 4 5 6 7 8 9 10 | >>> import time >>> import os >>> t = os.stat('C:/Path/To/File.txt').st_ctime >>> t = time.localtime(t) >>> formatted = time.strftime('%Y-%m-%d %H:%M:%S', t) >>> tz = str.format('{0:+06.2f}', float(time.timezone) / 3600) >>> final = formatted + tz >>> >>> final '2008-11-24 14:46:08-02.00' |
ISO  8601允许紧凑的表示,除了
1 2 | >>> datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%S.%fZ") '20180905T140903.591680Z' |
如果您不需要微秒,请忽略
1 2 | >>> datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") '20180905T140903Z' |
当地时间:
1 2 | >>> datetime.datetime.now().strftime("%Y%m%dT%H%M%S") '20180905T140903' |
如果我错了(我不是),请纠正我,但UTC的偏移会随着夏令时而变化。所以你应该使用
1 | tz = str.format('{0:+06.2f}', float(time.altzone) / 3600) |
我也相信标志应该是不同的:
1 | tz = str.format('{0:+06.2f}', -float(time.altzone) / 3600) |
我错了,但我不这么认为。
我同意Jarek,而且我还注意到ISO偏移分隔符是一个冒号,所以我认为最终的答案应该是:
1 | isodate.datetime_isoformat(datetime.datetime.now()) + str.format('{0:+06.2f}', -float(time.timezone) / 3600).replace('.', ':') |
我开发了这个功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def iso_8601_format(dt): """YYYY-MM-DDThh:mm:ssTZD (1997-07-16T19:20:30-03:00)""" if dt is None: return"" fmt_datetime = dt.strftime('%Y-%m-%dT%H:%M:%S') tz = dt.utcoffset() if tz is None: fmt_timezone ="+00:00" else: fmt_timezone = str.format('{0:+06.2f}', float(tz.total_seconds() / 3600)) return fmt_datetime + fmt_timezone |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import datetime, time def convert_enddate_to_seconds(self, ts): """Takes ISO 8601 format(string) and converts into epoch time.""" dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+\ datetime.timedelta(hours=int(ts[-5:-3]), minutes=int(ts[-2:]))*int(ts[-6:-5]+'1') seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0 return seconds >>> import datetime, time >>> ts = '2012-09-30T15:31:50.262-08:00' >>> dt = datetime.datetime.strptime(ts[:-7],'%Y-%m-%dT%H:%M:%S.%f')+ datetime.timedelta(hours=int(ts[-5:-3]), minutes=int(ts[-2:]))*int(ts[-6:-5]+'1') >>> seconds = time.mktime(dt.timetuple()) + dt.microsecond/1000000.0 >>> seconds 1348990310.26 |