问题:Python UTC日期时间对象的ISO格式不包含Z(Zulu或零偏移)
为什么python 2.7不像JavaScript那样在UTC日期时间对象的isoformat字符串的末尾不包含Z字符(Zulu或零偏移)?
>>> datetime.datetime.utcnow().isoformat()
'2013-10-29T09:14:03.895210'
而在javascript中
>>> console.log(new Date().toISOString());
2013-10-29T09:38:41.341Z
Why python 2.7 doesn’t include Z character (Zulu or zero offset) at the end of UTC datetime object’s isoformat string unlike JavaScript?
>>> datetime.datetime.utcnow().isoformat()
'2013-10-29T09:14:03.895210'
Whereas in javascript
>>> console.log(new Date().toISOString());
2013-10-29T09:38:41.341Z
回答 0
Python datetime
对象默认没有时区信息,没有它,Python实际上违反了ISO 8601规范(如果未提供时区信息,则假定为本地时间)。您可以使用pytz包获取一些默认时区,或者直接tzinfo
自己子类化:
from datetime import datetime, tzinfo, timedelta
class simple_utc(tzinfo):
def tzname(self,**kwargs):
return "UTC"
def utcoffset(self, dt):
return timedelta(0)
然后,您可以将时区信息手动添加到utcnow()
:
>>> datetime.utcnow().replace(tzinfo=simple_utc()).isoformat()
'2014-05-16T22:51:53.015001+00:00'
请注意,此DOES符合ISO 8601格式,该格式允许Z
或+00:00
作为UTC的后缀。请注意,后者实际上更好地符合了标准,并以一般方式表示时区(UTC是一种特例)。
Python datetime
objects don’t have time zone info by default, and without it, Python actually violates the ISO 8601 specification (if no time zone info is given, assumed to be local time). You can use the pytz package to get some default time zones, or directly subclass tzinfo
yourself:
from datetime import datetime, tzinfo, timedelta
class simple_utc(tzinfo):
def tzname(self,**kwargs):
return "UTC"
def utcoffset(self, dt):
return timedelta(0)
Then you can manually add the time zone info to utcnow()
:
>>> datetime.utcnow().replace(tzinfo=simple_utc()).isoformat()
'2014-05-16T22:51:53.015001+00:00'
Note that this DOES conform to the ISO 8601 format, which allows for either Z
or +00:00
as the suffix for UTC. Note that the latter actually conforms to the standard better, with how time zones are represented in general (UTC is a special case.)
回答 1
选项: isoformat()
Python datetime
不支持军事时区后缀,例如UTC的’Z’后缀。以下简单的字符串替换可以解决问题:
In [1]: import datetime
In [2]: d = datetime.datetime(2014, 12, 10, 12, 0, 0)
In [3]: str(d).replace('+00:00', 'Z')
Out[3]: '2014-12-10 12:00:00Z'
str(d)
基本上与 d.isoformat(sep=' ')
请参阅:日期时间,Python标准库
选项: strftime()
或者您可以使用strftime
以达到相同的效果:
In [4]: d.strftime('%Y-%m-%d %H:%M:%SZ')
Out[4]: '2014-12-10 12:00:00Z'
注意:仅当您知道指定的日期为UTC时,此选项才有效。
请参阅:datetime.strftime()
附加:人类可读的时区
更进一步,您可能对显示人类可读的时区信息感兴趣,pytz
带有strftime
%Z
时区标志:
In [5]: import pytz
In [6]: d = datetime.datetime(2014, 12, 10, 12, 0, 0, tzinfo=pytz.utc)
In [7]: d
Out[7]: datetime.datetime(2014, 12, 10, 12, 0, tzinfo=<UTC>)
In [8]: d.strftime('%Y-%m-%d %H:%M:%S %Z')
Out[8]: '2014-12-10 12:00:00 UTC'
Option: isoformat()
Python’s datetime
does not support the military timezone suffixes like ‘Z’ suffix for UTC. The following simple string replacement does the trick:
In [1]: import datetime
In [2]: d = datetime.datetime(2014, 12, 10, 12, 0, 0)
In [3]: str(d).replace('+00:00', 'Z')
Out[3]: '2014-12-10 12:00:00Z'
str(d)
is essentially the same as d.isoformat(sep=' ')
See: Datetime, Python Standard Library
Option: strftime()
Or you could use strftime
to achieve the same effect:
In [4]: d.strftime('%Y-%m-%d %H:%M:%SZ')
Out[4]: '2014-12-10 12:00:00Z'
Note: This option works only when you know the date specified is in UTC.
See: datetime.strftime()
Additional: Human Readable Timezone
Going further, you may be interested in displaying human readable timezone information, pytz
with strftime
%Z
timezone flag:
In [5]: import pytz
In [6]: d = datetime.datetime(2014, 12, 10, 12, 0, 0, tzinfo=pytz.utc)
In [7]: d
Out[7]: datetime.datetime(2014, 12, 10, 12, 0, tzinfo=<UTC>)
In [8]: d.strftime('%Y-%m-%d %H:%M:%S %Z')
Out[8]: '2014-12-10 12:00:00 UTC'
回答 2
以下javascript和python脚本提供相同的输出。我认为这就是您要寻找的。
的JavaScript
new Date().toISOString()
Python
import datetime
datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
他们给出的输出是utc(zelda)时间,格式为ISO字符串,有效数字为3毫秒,并附加Z。
2019-01-19T23:20:25.459Z
The following javascript and python scripts give identical outputs. I think it’s what you are looking for.
JavaScript
new Date().toISOString()
Python
from datetime import datetime
datetime.utcnow().isoformat()[:-3]+'Z'
The output they give is the utc (zelda) time formatted as an ISO string with a 3 millisecond significant digit and appended with a Z.
2019-01-19T23:20:25.459Z
回答 3
在Python> = 3.2中,您可以简单地使用以下代码:
>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc).isoformat()
'2019-03-14T07:55:36.979511+00:00'
In Python >= 3.2 you can simply use this:
>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc).isoformat()
'2019-03-14T07:55:36.979511+00:00'
回答 4
Python日期时间有点笨拙。使用arrow
。
> str(arrow.utcnow())
'2014-05-17T01:18:47.944126+00:00'
Arrow具有与datetime基本上相同的api,但是具有时区和一些其他优点,应该在主库中提供。
与Javascript兼容的格式可以通过以下方式实现:
arrow.utcnow().isoformat().replace("+00:00", "Z")
'2018-11-30T02:46:40.714281Z'
Javascript Date.parse
将从时间戳悄然下降微秒。
Python datetimes are a little clunky. Use arrow
.
> str(arrow.utcnow())
'2014-05-17T01:18:47.944126+00:00'
Arrow has essentially the same api as datetime, but with timezones and some extra niceties that should be in the main library.
A format compatible with Javascript can be achieved by:
arrow.utcnow().isoformat().replace("+00:00", "Z")
'2018-11-30T02:46:40.714281Z'
Javascript Date.parse
will quietly drop microseconds from the timestamp.
回答 5
帖子上有很多不错的答案,但我希望格式能像JavaScript一样准确。这就是我正在使用的并且效果很好。
In [1]: import datetime
In [1]: now = datetime.datetime.utcnow()
In [1]: now.strftime('%Y-%m-%dT%H:%M:%S') + now.strftime('.%f')[:4] + 'Z'
Out[3]: '2018-10-16T13:18:34.856Z'
There are a lot of good answers on the post, but I wanted the format to come out exactly as it does with JavaScript. This is what I’m using and it works well.
In [1]: import datetime
In [1]: now = datetime.datetime.utcnow()
In [1]: now.strftime('%Y-%m-%dT%H:%M:%S') + now.strftime('.%f')[:4] + 'Z'
Out[3]: '2018-10-16T13:18:34.856Z'
回答 6
pip install python-dateutil
>>> a = "2019-06-27T02:14:49.443814497Z"
>>> dateutil.parser.parse(a)
datetime.datetime(2019, 6, 27, 2, 14, 49, 443814, tzinfo=tzutc())
pip install python-dateutil
>>> a = "2019-06-27T02:14:49.443814497Z"
>>> dateutil.parser.parse(a)
datetime.datetime(2019, 6, 27, 2, 14, 49, 443814, tzinfo=tzutc())
回答 7
我通过一些目标解决了这个问题:
- 生成ISO 8601格式的UTC“感知”日期时间字符串
- 使用只有 Python标准库函数DateTime对象和字符串创建
- 使用Django
timezone
实用程序功能和dateutil
解析器验证datetime对象和字符串
- 使用JavaScript函数来验证ISO 8601日期时间字符串是否支持UTC
该方法不包含Z后缀,并且不使用utcnow()
,但是它基于Python文档中的建议,并且通过Django和JavaScript传递了标记。
让我们从传递UTC时区对象开始,datetime.now()
而不是使用datetime.utcnow()
:
from datetime import datetime, timezone
datetime.now(timezone.utc)
>>> datetime.datetime(2020, 1, 8, 6, 6, 24, 260810, tzinfo=datetime.timezone.utc)
datetime.now(timezone.utc).isoformat()
>>> '2020-01-08T06:07:04.492045+00:00'
这看起来不错,所以让我们看看Django和dateutil
思考:
from django.utils.timezone import is_aware
is_aware(datetime.now(timezone.utc))
>>> True
import dateutil.parser
is_aware(dateutil.parser.parse(datetime.now(timezone.utc).isoformat()))
>>> True
好的,Python日期时间对象和ISO 8601字符串都是UTC“可识别的”。现在,让我们看一下JavaScript对datetime字符串的看法。从这个答案中我们得到:
let date= '2020-01-08T06:07:04.492045+00:00';
const dateParsed = new Date(Date.parse(date))
document.write(dateParsed);
document.write("\n");
// Tue Jan 07 2020 22:07:04 GMT-0800 (Pacific Standard Time)
document.write(dateParsed.toISOString());
document.write("\n");
// 2020-01-08T06:07:04.492Z
document.write(dateParsed.toUTCString());
document.write("\n");
// Wed, 08 Jan 2020 06:07:04 GMT
您可能还想阅读此博客文章。
Pass a UTC timezone object to datetime.now()
instead of using datetime.utcnow()
:
from datetime import datetime, timezone
datetime.now(timezone.utc)
>>> datetime.datetime(2020, 1, 8, 6, 6, 24, 260810, tzinfo=datetime.timezone.utc)
datetime.now(timezone.utc).isoformat()
>>> '2020-01-08T06:07:04.492045+00:00'
That looks good, so let’s see what Django and dateutil
think:
from django.utils.timezone import is_aware
is_aware(datetime.now(timezone.utc))
>>> True
import dateutil.parser
is_aware(dateutil.parser.parse(datetime.now(timezone.utc).isoformat()))
>>> True
Okay, the Python datetime object and the ISO 8601 string are UTC “aware”. Now let’s look at what JavaScript thinks of the datetime string. Borrowing from this answer we get:
let date= '2020-01-08T06:07:04.492045+00:00';
const dateParsed = new Date(Date.parse(date))
document.write(dateParsed);
document.write("\n");
// Tue Jan 07 2020 22:07:04 GMT-0800 (Pacific Standard Time)
document.write(dateParsed.toISOString());
document.write("\n");
// 2020-01-08T06:07:04.492Z
document.write(dateParsed.toUTCString());
document.write("\n");
// Wed, 08 Jan 2020 06:07:04 GMT
Notes:
I approached this problem with a few goals:
- generate a UTC “aware” datetime string in ISO 8601 format
- use only Python Standard Library functions for datetime object and string creation
- validate the datetime object and string with the Django
timezone
utility function and the dateutil
parser
- use JavaScript functions to validate that the ISO 8601 datetime string is UTC aware
Note that this approach does not include a Z suffix and does not use utcnow()
. But it’s based on the recommendation in the Python documentation and it passes muster with both Django and JavaScript.
You may also want to read this blog post.
回答 8
通过结合以上所有答案,我得到了以下功能:
from datetime import datetime, tzinfo, timedelta
class simple_utc(tzinfo):
def tzname(self,**kwargs):
return "UTC"
def utcoffset(self, dt):
return timedelta(0)
def getdata(yy, mm, dd, h, m, s) :
d = datetime(yy, mm, dd, h, m, s)
d = d.replace(tzinfo=simple_utc()).isoformat()
d = str(d).replace('+00:00', 'Z')
return d
print getdata(2018, 02, 03, 15, 0, 14)
By combining all answers above I came with following function :
from datetime import datetime, tzinfo, timedelta
class simple_utc(tzinfo):
def tzname(self,**kwargs):
return "UTC"
def utcoffset(self, dt):
return timedelta(0)
def getdata(yy, mm, dd, h, m, s) :
d = datetime(yy, mm, dd, h, m, s)
d = d.replace(tzinfo=simple_utc()).isoformat()
d = str(d).replace('+00:00', 'Z')
return d
print getdata(2018, 02, 03, 15, 0, 14)
回答 9
我使用摆锤:
import pendulum
d = pendulum.now("UTC").to_iso8601_string()
print(d)
>>> 2019-10-30T00:11:21.818265Z
I use pendulum:
import pendulum
d = pendulum.now("UTC").to_iso8601_string()
print(d)
>>> 2019-10-30T00:11:21.818265Z
回答 10
>>> import arrow
>>> now = arrow.utcnow().format('YYYY-MM-DDTHH:mm:ss.SSS')
>>> now
'2018-11-28T21:34:59.235'
>>> zulu = "{}Z".format(now)
>>> zulu
'2018-11-28T21:34:59.235Z'
或者,一口气获得它:
>>> zulu = "{}Z".format(arrow.utcnow().format('YYYY-MM-DDTHH:mm:ss.SSS'))
>>> zulu
'2018-11-28T21:54:49.639Z'
>>> import arrow
>>> now = arrow.utcnow().format('YYYY-MM-DDTHH:mm:ss.SSS')
>>> now
'2018-11-28T21:34:59.235'
>>> zulu = "{}Z".format(now)
>>> zulu
'2018-11-28T21:34:59.235Z'
Or, to get it in one fell swoop:
>>> zulu = "{}Z".format(arrow.utcnow().format('YYYY-MM-DDTHH:mm:ss.SSS'))
>>> zulu
'2018-11-28T21:54:49.639Z'