Python UTC datetime object's ISO format doesn't include Z (Zulu or Zero offset)

ID : 20024

viewed : 27

Tags : pythonpython-2.7datetimetimestampiso8601python

Top 5 Answer for Python UTC datetime object's ISO format doesn't include Z (Zulu or Zero offset)

vote vote

90

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-%dT%H:%M:%SZ') Out[4]: '2014-12-10T12: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' 
vote vote

88

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.)

vote vote

74

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 
vote vote

64

Your goal shouldn't be to add a Z character, it should be to generate a UTC "aware" datetime string in ISO 8601 format. The solution is to 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  from dateutil.parser import isoparse is_aware(isoparse(datetime.now(timezone.utc).isoformat())) >>> True 

Note that you need to use isoparse() from dateutil.parser because the Python documentation for datetime.fromisoformat() says it "does not support parsing arbitrary ISO 8601 strings".

Okay, the Python datetime object and the ISO 8601 string are both 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, the dateutil parser and JavaScript functions

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.

See also:

vote vote

58

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' 

Top 3 video Explaining Python UTC datetime object's ISO format doesn't include Z (Zulu or Zero offset)

Related QUESTION?