Python 3 How to format to yyyy-mm-ddThh:mm:ssZ

68.4k views Asked by At

I'm new to Python and I cannot for the life of me find my specific answer online. I need to format a timestamp to this exact format to include 'T', 'Z' and no sub or miliseconds like this yyyy-mm-ddThh:mm:ssZ i.e. 2019-03-06T11:22:00Z. There's lots of stuff on parsing this format but nothing about formatting this way. The only way I have nearly got it to work involves sub-seconds which I do not need. I've tried using arrow and reading their documentation but unable to get anything to work. Any help would be appreciated.

4

There are 4 answers

1
skaul05 On BEST ANSWER

Try datetime library

import datetime

output_date = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
print(output_date)

For more information, refer to the Python Documentation.

0
questionto42 On

With f strings, you can shorten it down to:

from datetime import datetime

f'{datetime.now():%Y-%m-%dT%H:%M:%SZ}'

Credits go to How do I turn a python datetime into a string, with readable format date?.

0
ra67052 On

Thanks to skaul05 I managed to get the code I needed, it's

date = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
print(date)
2
Sam On

Be careful. Just be cause a date can be formatted to look like UTC, doesn't mean it's accurate.

In ISO 8601, 'Z' is meant to designate "zulu time" or UTC ('+00:00'). While local times are typically designated by their offset from UTC. Even worse, these offsets can change throughout a year due to Daylight Saving Time (DST).

So unless you live in England in the winter or Iceland in the summer, chances are, you aren't lucky enough to be working with UTC locally, and your timestamps will be completely wrong.

Python3.8

from datetime import datetime, timezone

# a naive datetime representing local time
naive_dt = datetime.now()

# incorrect, local (MST) time made to look like UTC (very, very bad)
>>> naive_dt.strftime("%Y-%m-%dT%H:%M:%SZ")
'2020-08-27T20:57:54Z'   # actual UTC == '2020-08-28T02:57:54Z'

# so we'll need an aware datetime (taking your timezone into consideration)
# NOTE: I imagine this works with DST, but I haven't verified

aware_dt = naive_dt.astimezone()

# correct, ISO-8601 (but not UTC)
>>> aware_dt.isoformat(timespec='seconds')
'2020-08-27T20:57:54-06:00'

# lets get the time in UTC
utc_dt = aware_dt.astimezone(timezone.utc)

# correct, ISO-8601 and UTC (but not in UTC format)
>>> utc_dt.isoformat(timespec='seconds')
'2020-08-28T02:57:54+00:00'

# correct, UTC format (this is what you asked for)
>>> date_str = utc_dt.isoformat(timespec='seconds')
>>> date_str.replace('+00:00', 'Z')
'2020-08-28T02:57:54Z'

# Perfect UTC format
>>> date_str = utc_dt.isoformat(timespec='milliseconds')
>>> date_str.replace('+00:00', 'Z')
'2020-08-28T02:57:54.640Z'

I just wanted to illustrate some things above, there are much simpler ways:

from datetime import datetime, timezone


def utcformat(dt, timespec='milliseconds'):
    """convert datetime to string in UTC format (YYYY-mm-ddTHH:MM:SS.mmmZ)"""
    iso_str = dt.astimezone(timezone.utc).isoformat('T', timespec)
    return iso_str.replace('+00:00', 'Z')


def fromutcformat(utc_str, tz=None):
    iso_str = utc_str.replace('Z', '+00:00')
    return datetime.fromisoformat(iso_str).astimezone(tz)


now = datetime.now(tz=timezone.utc)

# default with milliseconds ('2020-08-28T02:57:54.640Z')
print(utcformat(now))

# without milliseconds ('2020-08-28T02:57:54Z')
print(utcformat(now, timespec='seconds'))


>>> utc_str1 = '2020-08-28T04:35:35.455Z'
>>> dt = fromutcformat(utc_string)
>>> utc_str2 = utcformat(dt)
>>> utc_str1 == utc_str2
True

# it even converts naive local datetimes correctly (as of Python 3.8)
>>> now = datetime.now()
>>> utc_string = utcformat(now)

>>> converted = fromutcformat(utc_string)
>>> now.astimezone() - converted
timedelta(microseconds=997)