Sling Academy
Home/Python/Python: 2 Ways to Check if a Date String is Valid

Python: 2 Ways to Check if a Date String is Valid

Last updated: June 15, 2023

Overview

In general (and in the context of this article), a valid date string can be considered a date string in the ISO 8601 format. The ISO 8601 format is an internationally recognized standard for representing dates and times in consistent and unambiguous ways.

By considering a valid date string as one that adheres to the ISO 8601 format, you ensure that the date is represented correctly and can be easily understood by others who are familiar with the standard. This format is widely used in various industries and systems, making it a reliable choice for date representation.

In Python, an invalid date string cannot be parsed into a date or a datetime object by the datetime module. An invalid date string can be very similar to a valid one and easy to fool our eyes:

  • The string contains ambiguous or conflicting information, such as 02/03/04 (could be February 3rd 2004, March 2nd 2004, or April 3rd 2002).
  • The string does not match any of the expected formats.
  • The string contains invalid values for year, month, day, hour, minute, second, microsecond, or timezone.

Some examples of invalid date strings are:

"2023-13-01" # month cannot be 13
"2021-02-29" # February 29th does not exist in 2021
"2024-01-32" # day cannot be 32
"2023-01-01 25:00:00" # hour cannot be 25
"2025-01-01 12:00:00 PM UTC+0100" # conflicting timezone information
"02/03/04" # ambiguous format

Checking if a Date String is Valid

Some different ways to know whether a given string is a true representation of a date object.

Using datetime.fromisoformat()

The main idea of this approach is to use the datetime.fromisoformat() class method of the datetime module to parse a date string in ISO 8601 format and return a datetime object. If the string is not a valid ISO 8601 date string, it raises a ValueError exception.

Example:

from datetime import datetime

def is_valid_date(date_str):
  # Checks if a date string is valid ISO 8601 format
  # Returns True if valid, False otherwise
  try:
    datetime.fromisoformat(date_str)
    return True
  except ValueError:
    return False

# Test cases
print(is_valid_date("2023-06-15")) # True
print(is_valid_date("2024-06-15T10:44:50")) # True
print(is_valid_date("2023-06-15T10:44:50.123456")) # True
print(is_valid_date("2024-06-15T10:44:50+07:00")) # True
print(is_valid_date("2024-02-29")) # True (2024 is a leap year
print(is_valid_date("2025-02-29")) # False (2025 is not a leap year)
print(is_valid_date("2024-06-15T10:44:50Z")) # False
print(is_valid_date("2021-13-15")) # False

This technique has some pros and cons, as shown below:

  • Pros: This solution is simple and does not require any external libraries. It can handle different variations of ISO 8601 format, such as YYYY-MM-DD, YYYY-MM-DDTHH:MM:SS, YYYY-MM-DDTHH:MM:SS.mmmmmm, YYYY-MM-DDTHH:MM:SS+HH:MM, etc.
  • Cons: This solution requires Python 3.7 or higher. It does not support the Z suffix for UTC timezone, such as YYYY-MM-DDTHH:MM:SSZ. It may also raise other exceptions, such as TypeError or OverflowError, if the input is not a string or has invalid values.

In case you have to deal with the Z suffix for UTC timezone, see the next solution.

Using dateutil.parse.isoparse()

In this approach, we’ll use the isoparse() function from the dateutil.parser module to parse a date string in ISO 8601 format and return a datetime object. If the string is not a valid ISO 8601 date string, it will raise a ValueError exception.

dateutil is not ready to use by default. You need to install it first:

pip install python-dateutil

Code example:

from dateutil.parser import isoparse

def is_valid_date(date_str):
  # Checks if a date string is valid ISO 8601 format
  # Returns True if valid, False otherwise
  try:
    isoparse(date_str)
    return True
  except ValueError:
    return False

# Test cases
print(is_valid_date("2024-06-15")) # True
print(is_valid_date("2025-06-15T10:44:50")) # True
print(is_valid_date("2023-06-15T10:44:50.123456")) # True
print(is_valid_date("2025-06-15T10:44:50+07:00")) # True
print(is_valid_date("2023-06-15T10:44:50Z")) # True
print(is_valid_date("2024-13-15")) # False (invalid month)
print(is_valid_date("2025-02-29")) # False (2025 is not a leap year)
print(is_valid_date("2023-06-15T10:44:50.1234567")) # True

Some considerations about this technique:

  • Advantages: This solution can handle different variations of ISO 8601 format, such as YYYY-MM-DD, YYYY-MM-DDTHH:MM:SS, YYYY-MM-DDTHH:MM:SS.mmmmmm, YYYY-MM-DDTHH:MM:SS+HH:MM, etc. It also supports the Z suffix for UTC timezone, such as YYYY-MM-DDTHH:MM:SSZ so it is more reliable than using datetime.fromisoformat().
  • Disadvantages: This solution requires installing an external library. It may also raise other exceptions, such as TypeError or OverflowError, if the input is not a string or has invalid values.

Conclusion

You’ve learned a couple of different ways to check the validity of a date string in Python. If you don’t care about the timezone (such as when you build software specifically for a certain city), the first one is good enough. In other situations, the second one is safer.

Next Article: Python: Get the Current Date and Time with Timezone

Previous Article: How to Format Date and Time in Python

Series: Date and Time in Python

Python

You May Also Like

  • Introduction to yfinance: Fetching Historical Stock Data in Python
  • Monitoring Volatility and Daily Averages Using cryptocompare
  • Advanced DOM Interactions: XPath and CSS Selectors in Playwright (Python)
  • Automating Strategy Updates and Version Control in freqtrade
  • Setting Up a freqtrade Dashboard for Real-Time Monitoring
  • Deploying freqtrade on a Cloud Server or Docker Environment
  • Optimizing Strategy Parameters with freqtrade’s Hyperopt
  • Risk Management: Setting Stop Loss, Trailing Stops, and ROI in freqtrade
  • Integrating freqtrade with TA-Lib and pandas-ta Indicators
  • Handling Multiple Pairs and Portfolios with freqtrade
  • Using freqtrade’s Backtesting and Hyperopt Modules
  • Developing Custom Trading Strategies for freqtrade
  • Debugging Common freqtrade Errors: Exchange Connectivity and More
  • Configuring freqtrade Bot Settings and Strategy Parameters
  • Installing freqtrade for Automated Crypto Trading in Python
  • Scaling cryptofeed for High-Frequency Trading Environments
  • Building a Real-Time Market Dashboard Using cryptofeed in Python
  • Customizing cryptofeed Callbacks for Advanced Market Insights
  • Integrating cryptofeed into Automated Trading Bots