📝 Parsing Date Strings

Converting date strings into Python datetime objects is crucial for processing user input, reading data files, and handling dates from various sources. Python's strptime() method provides powerful parsing capabilities for different date formats.

from datetime import datetime

# Parse different date string formats
date_strings = [
    "2024-03-15",
    "03/15/2024",
    "March 15, 2024",
    "2024-03-15 14:30:45"
]

formats = [
    "%Y-%m-%d",
    "%m/%d/%Y", 
    "%B %d, %Y",
    "%Y-%m-%d %H:%M:%S"
]

for date_str, fmt in zip(date_strings, formats):
    parsed = datetime.strptime(date_str, fmt)
    print(f"'{date_str}' → {parsed}")

🎯 Understanding strptime()

The strptime() method converts strings to datetime objects using format codes.

Basic String Parsing

from datetime import datetime

# Common date formats
iso_date = datetime.strptime("2024-03-15", "%Y-%m-%d")
us_date = datetime.strptime("03/15/2024", "%m/%d/%Y")
european_date = datetime.strptime("15/03/2024", "%d/%m/%Y")

print(f"ISO date: {iso_date}")
print(f"US date: {us_date}")  
print(f"European date: {european_date}")

# Date with time
datetime_str = "2024-03-15 14:30:45"
full_datetime = datetime.strptime(datetime_str, "%Y-%m-%d %H:%M:%S")
print(f"Full datetime: {full_datetime}")

Handling Different Time Formats

from datetime import datetime

# Various time formats
time_formats = [
    ("14:30:45", "%H:%M:%S"),           # 24-hour
    ("2:30:45 PM", "%I:%M:%S %p"),      # 12-hour with AM/PM
    ("2:30 PM", "%I:%M %p"),            # 12-hour without seconds
    ("14:30", "%H:%M"),                 # 24-hour without seconds
]

for time_str, fmt in time_formats:
    try:
        # Parse time only (date defaults to 1900-01-01)
        parsed = datetime.strptime(time_str, fmt)
        print(f"'{time_str}' → {parsed.time()}")
    except ValueError as e:
        print(f"Error parsing '{time_str}': {e}")

Named Month Parsing

from datetime import datetime

# Different month name formats
month_formats = [
    ("March 15, 2024", "%B %d, %Y"),        # Full month name
    ("Mar 15, 2024", "%b %d, %Y"),          # Abbreviated month
    ("15 March 2024", "%d %B %Y"),          # Day first
    ("2024, March 15", "%Y, %B %d"),        # Year first
]

for date_str, fmt in month_formats:
    try:
        parsed = datetime.strptime(date_str, fmt)
        print(f"'{date_str}' → {parsed.strftime('%Y-%m-%d')}")
    except ValueError as e:
        print(f"Error: {e}")

🛠️ Flexible Date Parsing

Handle multiple formats and provide robust parsing solutions.

Multi-Format Parser

from datetime import datetime

def parse_date_flexible(date_string):
    """Try to parse date string with multiple formats"""
    formats = [
        "%Y-%m-%d",           # 2024-03-15
        "%m/%d/%Y",           # 03/15/2024
        "%d/%m/%Y",           # 15/03/2024
        "%B %d, %Y",          # March 15, 2024
        "%b %d, %Y",          # Mar 15, 2024
        "%d %B %Y",           # 15 March 2024
        "%Y-%m-%d %H:%M:%S",  # 2024-03-15 14:30:45
        "%m/%d/%Y %I:%M %p",  # 03/15/2024 2:30 PM
    ]
    
    for fmt in formats:
        try:
            return datetime.strptime(date_string, fmt)
        except ValueError:
            continue
    
    raise ValueError(f"Unable to parse date: {date_string}")

# Test with various formats
test_dates = [
    "2024-03-15",
    "03/15/2024", 
    "March 15, 2024",
    "2024-03-15 14:30:45",
    "Invalid date"
]

for date_str in test_dates:
    try:
        parsed = parse_date_flexible(date_str)
        print(f"✓ '{date_str}' → {parsed}")
    except ValueError as e:
        print(f"✗ {e}")

Fuzzy Date Parsing

from datetime import datetime
import re

def clean_and_parse_date(date_string):
    """Clean and parse date strings with extra text"""
    # Remove common extra words and characters
    cleaned = re.sub(r'\b(on|at|the)\b', '', date_string, flags=re.IGNORECASE)
    cleaned = re.sub(r'[,]+', ',', cleaned)  # Multiple commas
    cleaned = re.sub(r'\s+', ' ', cleaned).strip()  # Multiple spaces
    
    # Try parsing the cleaned string
    formats = [
        "%B %d %Y",          # March 15 2024
        "%B %d, %Y",         # March 15, 2024
        "%m/%d/%Y",          # 03/15/2024
        "%Y-%m-%d",          # 2024-03-15
    ]
    
    for fmt in formats:
        try:
            return datetime.strptime(cleaned, fmt)
        except ValueError:
            continue
    
    raise ValueError(f"Could not parse: {date_string}")

# Test fuzzy parsing
fuzzy_dates = [
    "on March 15, 2024",
    "the 15th of March, 2024", 
    "March  15,,,  2024",
    "at 03/15/2024"
]

for date_str in fuzzy_dates:
    try:
        parsed = clean_and_parse_date(date_str)
        print(f"✓ '{date_str}' → {parsed.strftime('%Y-%m-%d')}")
    except ValueError:
        print(f"✗ Could not parse: '{date_str}'")

Date Validation

from datetime import datetime

def validate_and_parse_date(date_string, min_year=1900, max_year=2100):
    """Parse and validate date with reasonable limits"""
    try:
        # Try common formats
        formats = ["%Y-%m-%d", "%m/%d/%Y", "%d/%m/%Y", "%B %d, %Y"]
        
        parsed_date = None
        for fmt in formats:
            try:
                parsed_date = datetime.strptime(date_string, fmt)
                break
            except ValueError:
                continue
        
        if parsed_date is None:
            return None, "Invalid date format"
        
        # Validate year range
        if not (min_year <= parsed_date.year <= max_year):
            return None, f"Year must be between {min_year} and {max_year}"
        
        # Validate not in future (optional check)
        if parsed_date > datetime.now():
            return None, "Date cannot be in the future"
        
        return parsed_date, "Valid"
        
    except Exception as e:
        return None, f"Error: {str(e)}"

# Test date validation
test_dates = [
    "2024-03-15",      # Valid
    "13/15/2024",      # Invalid month
    "2025-12-31",      # Future date
    "1800-01-01",      # Too old
    "invalid",         # Invalid format
]

for date_str in test_dates:
    result, message = validate_and_parse_date(date_str)
    status = "✓" if result else "✗"
    print(f"{status} '{date_str}': {message}")
    if result:
        print(f"   Parsed as: {result.strftime('%B %d, %Y')}")

📊 Format Code Reference for Parsing

Essential Parse Formats

FormatPatternExample Input
%Y-%m-%dISO date2024-03-15
%m/%d/%YUS date03/15/2024
%d/%m/%YEuropean date15/03/2024
%B %d, %YFull monthMarch 15, 2024
%b %d, %YShort monthMar 15, 2024
%Y-%m-%d %H:%M:%SISO datetime2024-03-15 14:30:45
%m/%d/%Y %I:%M %pUS datetime03/15/2024 2:30 PM

Time Zone Parsing

from datetime import datetime

# Parsing dates with timezone info (basic)
def parse_with_timezone_info(date_string):
    """Parse dates that might contain timezone info"""
    # Remove common timezone indicators for basic parsing
    cleaned = date_string
    tz_patterns = [' UTC', ' GMT', ' EST', ' PST', ' CST', ' MST']
    
    for pattern in tz_patterns:
        if pattern in cleaned:
            cleaned = cleaned.replace(pattern, '')
            print(f"Removed timezone: {pattern.strip()}")
    
    # Parse the cleaned datetime
    try:
        return datetime.strptime(cleaned, "%Y-%m-%d %H:%M:%S")
    except ValueError:
        return datetime.strptime(cleaned, "%m/%d/%Y %H:%M:%S")

# Example usage
tz_dates = [
    "2024-03-15 14:30:45 UTC",
    "03/15/2024 14:30:45 EST"
]

for date_str in tz_dates:
    try:
        parsed = parse_with_timezone_info(date_str)
        print(f"'{date_str}' → {parsed}")
    except ValueError as e:
        print(f"Error: {e}")

🎯 Key Takeaways

🚀 What's Next?

Now that you can parse date strings, learn how to handle time zones for global applications.

Continue to: Handle Timezones

Was this helpful?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent