Convert between isoformat string and datetime in Python

Modified: | Tags: Python, Date and time

In Python, you can handle date and time information with the datetime module from the standard library.

The datetime module provides methods, such as isoformat() and fromisoformat(), for converting between ISO format (ISO 8601) strings and datetime objects.

For an introduction to datetime, date, and time objects, as well as conversion between specific format strings and datetime objects, refer to the following article.

Convert date and time objects to isoformat strings: isoformat()

To convert date and time objects to ISO format (ISO 8601) strings, use the isoformat() method on date, time, and datetime objects.

Convert a date object to an isoformat string

Consider the following date object.

import datetime

d = datetime.date(2023, 4, 1)
print(d)
# 2023-04-01

print(type(d))
# <class 'datetime.date'>

You can convert a date object to an isoformat string using isoformat().

print(d.isoformat())
# 2023-04-01

print(type(d.isoformat()))
# <class 'str'>

Convert a time object to an isoformat string

Consider the following time object.

t = datetime.time(5, 0, 30, 1000)
print(t)
# 05:00:30.001000

print(type(t))
# <class 'datetime.time'>

You can convert a time object to an isoformat string using isoformat().

print(t.isoformat())
# 05:00:30.001000

print(type(t.isoformat()))
# <class 'str'>

You can control the elements included in the result using the timespec argument. By default, timespec is set to 'auto', which sets timespec to 'seconds' if microseconds are 0, and to 'microseconds' otherwise.

print(t.isoformat('hours'))
# 05

print(t.isoformat('minutes'))
# 05:00

print(t.isoformat('seconds'))
# 05:00:30

print(t.isoformat('milliseconds'))
# 05:00:30.001

print(t.isoformat('microseconds'))
# 05:00:30.001000

Convert a datetime object to an isoformat string

Consider the following datetime object.

dt = datetime.datetime(2023, 4, 1, 5, 0, 30, 1000)
print(dt)
# 2023-04-01 05:00:30.001000

print(type(dt))
# <class 'datetime.datetime'>

You can convert a datetime object to an isoformat string using isoformat().

print(dt.isoformat())
# 2023-04-01T05:00:30.001000

print(type(dt.isoformat()))
# <class 'str'>

The default character separating the date and time is T. You can specify a different single character using the first argument sep. Providing a string with two or more characters will cause an error.

print(dt.isoformat(' '))
# 2023-04-01 05:00:30.001000

print(dt.isoformat('x'))
# 2023-04-01x05:00:30.001000

# print(dt.isoformat('xx'))
# TypeError: isoformat() argument 1 must be a unicode character, not str

As with the time object, you can control the elements included in the result using the timespec argument. By default, timespec is set to 'auto', which sets timespec to 'seconds' if microseconds are 0, and to 'microseconds' otherwise.

print(dt.isoformat(timespec='hours'))
# 2023-04-01T05

print(dt.isoformat(timespec='minutes'))
# 2023-04-01T05:00

print(dt.isoformat(timespec='seconds'))
# 2023-04-01T05:00:30

print(dt.isoformat(timespec='milliseconds'))
# 2023-04-01T05:00:30.001

print(dt.isoformat(timespec='microseconds'))
# 2023-04-01T05:00:30.001000

To convert a datetime object to a date-only or time-only string, first use the date() or time() methods to create the corresponding object, and then call the isoformat() method on that object.

print(dt.date().isoformat())
# 2023-04-01

print(dt.time().isoformat())
# 05:00:30.001000

Convert isoformat strings to date and time objects: fromisoformat()

To convert an ISO format (ISO 8601) string to date, time, and datetime objects, use the fromisoformat() method of the date, time, and datetime classes.

fromisoformat() was added in Python 3.7. Additionally, as described later, it supports the ISO 8601 basic format starting from Python 3.11.

Convert an isoformat string to a date object

You can convert an isoformat string to a date object using fromisoformat().

d = datetime.date.fromisoformat('2023-04-01')
print(d)
# 2023-04-01

print(type(d))
# <class 'datetime.date'>

An error will be raised if the year, month, or day is omitted or has an incorrect number of digits. The year should have 4 digits, while the month and day should each have 2 digits, zero-padded.

# print(datetime.date.fromisoformat('2023-04'))
# ValueError: Invalid isoformat string: '2023-04'

# print(datetime.date.fromisoformat('2023-4-1'))
# ValueError: Invalid isoformat string: '2023-4-1'

Convert an isoformat string to a time object

You can convert an isoformat string to a time object using fromisoformat().

t = datetime.time.fromisoformat('05:00:30.001000')
print(t)
# 05:00:30.001000

print(type(t))
# <class 'datetime.time'>

If minutes, seconds, or microseconds are omitted, they will be treated as 0.

print(datetime.time.fromisoformat('05'))
# 05:00:00

An error will be raised if the hours, minutes, and seconds are not represented as zero-padded two-digit numbers.

# print(datetime.time.fromisoformat('5:00:30'))
# ValueError: Invalid isoformat string: '5:00:30'

Convert an isoformat string to a datetime object

You can convert an isoformat string to a datetime object using fromisoformat().

dt = datetime.datetime.fromisoformat('2023-04-01T05:00:30.001000')
print(dt)
# 2023-04-01 05:00:30.001000

print(type(dt))
# <class 'datetime.datetime'>

Any single character other than T between the date and time is acceptable, but two or more characters will cause an error.

print(datetime.datetime.fromisoformat('2023-04-01x05:00:30.001000'))
# 2023-04-01 05:00:30.001000

# print(datetime.datetime.fromisoformat('2023-04-01xx05:00:30.001000'))
# ValueError: Invalid isoformat string: '2023-04-01xx05:00:30.001000'

If minutes and seconds are omitted, they will be treated as 0.

print(datetime.datetime.fromisoformat('2023-04-01T05'))
# 2023-04-01 05:00:00

print(datetime.datetime.fromisoformat('2023-04-01'))
# 2023-04-01 00:00:00

Like with date and time objects, an error will occur if the number of digits is incorrect. Zero-padding is required.

# print(datetime.datetime.fromisoformat('2023-4-1T5:00'))
# ValueError: Invalid isoformat string: '2023-4-1T5:00'

To convert a string containing both date and time to date and time objects, first convert it to a datetime object, and then call the date() and time() methods on that object.

s = '2023-04-01T05:00:30.001000'

# print(datetime.date.fromisoformat(s))
# ValueError: Invalid isoformat string: '2023-04-01T05:00:30.001000'

d = datetime.datetime.fromisoformat(s).date()
print(d)
# 2023-04-01

print(type(d))
# <class 'datetime.date'>

ISO 8601 basic and extended formats

ISO 8601 has an extended format that includes hyphens - and colons : as separators, and a basic format that does not.

  • Basic format: 20230401T050030.001000
  • Extended format: 2023-04-01T05:00:30.001000

fromisoformat() supports basic format from Python 3.11

Starting from Python 3.11, fromisoformat() supports the basic format.

print(datetime.date.fromisoformat('20230401'))
# 2023-04-01

print(datetime.time.fromisoformat('050030.001000'))
# 05:00:30.001000

print(datetime.datetime.fromisoformat('20230401T050030.001000'))
# 2023-04-01 05:00:30.001000

In earlier versions, you need to specify an appropriate format string for strptime().

print(datetime.datetime.strptime('20230401T050030.001000', '%Y%m%dT%H%M%S.%f'))
# 2023-04-01 05:00:30.001000

Convert between basic and extended format strings

As demonstrated above, isoformat() outputs an extended format string. To obtain a basic format string, use string manipulation methods.

For example, use replace() to remove hyphens - and colons :.

s = '2023-04-01T05:00:30.001000'
print(s.replace('-', '').replace(':', ''))
# 20230401T050030.001000

To exclude milliseconds and smaller units, use the split() method to separate the string at the decimal point ., and select the first element.

print(s.split('.')[0].replace('-', '').replace(':', ''))
# 20230401T050030

To convert a basic format string to an extended format, first convert the basic format string to a datetime object, and then use the isoformat() method to obtain the extended format string. As mentioned above, use fromisoformat() for Python 3.11 and later, and strptime() for earlier versions.

s_basic = '20230401T050030.001000'
print(datetime.datetime.fromisoformat(s_basic).isoformat())
# 2023-04-01T05:00:30.001000

Handling timezone information

When converting a string without timezone information using fromisoformat() as shown in the previous examples, the tzinfo attribute will be None.

s = '2023-04-01T05:00:30.001000'
dt = datetime.datetime.fromisoformat(s)
print(dt)
# 2023-04-01 05:00:30.001000

print(dt.tzinfo)
# None

If a string includes timezone information like +09:00 at the end, the tzinfo attribute will have a value.

s = '2023-04-01T05:00:30.001000+09:00'
dt = datetime.datetime.fromisoformat(s)
print(dt)
# 2023-04-01 05:00:30.001000+09:00

print(dt.tzinfo)
# UTC+09:00

When the tzinfo attribute has a value, the isoformat() method appends a timezone string to the end of the output string according to that value.

print(dt.isoformat())
# 2023-04-01T05:00:30.001000+09:00

Isoformat string with Z

When representing UTC (Coordinated Universal Time), a trailing Z is added.

Python 3.11 and later

Starting from Python 3.11, fromisoformat() correctly handles trailing Z.

s = '2023-04-01T05:00:30.001000Z'
dt = datetime.datetime.fromisoformat(s)
print(dt)
# 2023-04-01 05:00:30.001000+00:00

print(dt.tzinfo)
# UTC

Before Python 3.11

In versions prior to Python 3.11, a string with a trailing Z will cause an error with fromisoformat().

To handle a trailing Z, you can replace it with +00:00. In this case, the tzinfo attribute will contain the appropriate timezone information.

s = '2023-04-01T05:00:30.001000Z'
dt_utc = datetime.datetime.fromisoformat(s.replace('Z', '+00:00'))
print(dt_utc)
# 2023-04-01 05:00:30.001000+00:00

print(dt_utc.tzinfo)
# UTC

If you remove the trailing Z, the tzinfo attribute will be None. This approach can be used if timezone information is not necessary for your use case.

dt_none = datetime.datetime.fromisoformat(s.replace('Z', ''))
print(dt_none)
# 2023-04-01 05:00:30.001000

print(dt_none.tzinfo)
# None

Related Categories

Related Articles