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

28,001

Solution 1

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.

Solution 2

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)

Solution 3

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)
Share:
28,001
ra67052
Author by

ra67052

I'm a guy who has started to transition into IT after spending all of my career thus far in the business. I have always wanted to learn to code and have started to learn Python when life allows me

Updated on February 04, 2021

Comments

  • ra67052
    ra67052 over 3 years

    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.