Applications must display dates in user-friendly formats and parse dates from user input or files. Python's strftime() converts dates to strings using format codes, while strptime() parses strings back to dates. Mastering these functions enables proper date handling in APIs, logs, and user interfaces.

DateTime formatting converts date/time objects to human-readable strings using patterns. Python uses strftime() for formatting and strptime() for parsing.

Formatting to Strings

format.py
Replay: real traced execution (multi-file project)
# Format to string

from datetime import datetime, date, time

# Format datetime
dt = datetime(2025, 1, 29, 14, 30, 45)

print("DateTime:", dt)
print()

# ISO format
print("ISO formats:")
print("ISO format:", dt.isoformat())
print("ISO date:", dt.date().isoformat())
print("ISO time:", dt.time().isoformat())

# Common patterns
print("\nCommon patterns:")
print("%Y-%m-%d %H:%M:%S:", dt.strftime("%Y-%m-%d %H:%M:%S"))
print("%m/%d/%Y:", dt.strftime("%m/%d/%Y"))
print("%d-%b-%Y:", dt.strftime("%d-%b-%Y"))
print("%A, %B %d, %Y:", dt.strftime("%A, %B %d, %Y"))

# Time formats
print("\nTime formats:")
print("24-hour:", dt.strftime("%H:%M:%S"))
print("12-hour:", dt.strftime("%I:%M %p"))

# Date only
d = date(2025, 1, 29)
print("\nDate only:")
print("ISO:", d.isoformat())
print("US:", d.strftime("%m/%d/%Y"))
print("EU:", d.strftime("%d/%m/%Y"))
print("Full:", d.strftime("%A, %B %d, %Y"))

# Time only
t = time(14, 30, 45)
print("\nTime only:")
print("ISO:", t.isoformat())
print("Simple:", t.strftime("%H:%M"))
print("12-hour:", t.strftime("%I:%M %p"))

# Default str()
print("\nDefault str():")
print("Date:", str(d))
print("Time:", str(t))
print("DateTime:", str(dt))

# Format codes reference
print("\nFormat codes:")
codes = [
    ("%Y", "4-digit year"),
    ("%y", "2-digit year"),
    ("%m", "2-digit month"),
    ("%B", "Full month name"),
    ("%b", "Short month name"),
    ("%d", "2-digit day"),
    ("%A", "Full day name"),
    ("%a", "Short day name"),
    ("%H", "24-hour (00-23)"),
    ("%I", "12-hour (01-12)"),
    ("%M", "Minute"),
    ("%S", "Second"),
    ("%p", "AM/PM")
]

for code, description in codes:
    try:
        value = dt.strftime(code)
        print(f"{code}: {description} = {value}")
    except:
        pass

  1. dt ← 2025-01-29 14:30:45, d ← 2025-01-29, t ← 14:30:45, codes ← [('%Y', '4-digit year'), ('%y', '2-digit year'), ('%m', '2-digit month'), ('%B', 'Full month name'), ('%b', 'Short month name'), ('%d', '2-digit day'), ('%A', 'Full day name'), ('%a', 'Short day name'), ('%H', '24-hour (00-23)'), ('%I', '12-hour (01-12)'), ('%M', 'Minute'), ('%S', 'Second'), ('%p', 'AM/PM')]

    5# Format datetime6dt→ 2025-01-29 14:30:45 = datetime(2025, 1, 29, 14, 30, 45)78print("DateTime:", dt2025-01-29 14:30:45)9print()1011# ISO format12print("ISO formats:")13print("ISO format:", dt2025-01-29 14:30:45.isoformat())14print("ISO date:", dt2025-01-29 14:30:45.date().isoformat())15print("ISO time:", dt2025-01-29 14:30:45.time().isoformat())1617# Common patterns18print("\nCommon patterns:")19print("%Y-%m-%d %H:%M:%S:", dt2025-01-29 14:30:45.strftime("%Y-%m-%d %H:%M:%S"))20print("%m/%d/%Y:", dt2025-01-29 14:30:45.strftime("%m/%d/%Y"))21print("%d-%b-%Y:", dt2025-01-29 14:30:45.strftime("%d-%b-%Y"))22print("%A, %B %d, %Y:", dt2025-01-29 14:30:45.strftime("%A, %B %d, %Y"))2324# Time formats25print("\nTime formats:")26print("24-hour:", dt2025-01-29 14:30:45.strftime("%H:%M:%S"))27print("12-hour:", dt2025-01-29 14:30:45.strftime("%I:%M %p"))2829# Date only30d→ 2025-01-29 = date(2025, 1, 29)31print("\nDate only:")32print("ISO:", d2025-01-29.isoformat())33print("US:", d2025-01-29.strftime("%m/%d/%Y"))34print("EU:", d2025-01-29.strftime("%d/%m/%Y"))35print("Full:", d2025-01-29.strftime("%A, %B %d, %Y"))3637# Time only38t→ 14:30:45 = time(14, 30, 45)39print("\nTime only:")40print("ISO:", t14:30:45.isoformat())41print("Simple:", t14:30:45.strftime("%H:%M"))42print("12-hour:", t14:30:45.strftime("%I:%M %p"))4344# Default str()45print("\nDefault str():")46print("Date:", str(d2025-01-29))47print("Time:", str(t14:30:45))48print("DateTime:", str(dt2025-01-29 14:30:45))4950# Format codes reference51print("\nFormat codes:")52codes→ [('%Y', '4-digit year'), ('%y', '2-digit year'), ('%m', '2-digit month'), ('%B', 'Full month name'), ('%b', 'Short month name'), ('%d', '2-digit day'), ('%A', 'Full day name'), ('%a', 'Short day name'), ('%H', '24-hour (00-23)'), ('%I', '12-hour (01-12)'), ('%M', 'Minute'), ('%S', 'Second'), ('%p', 'AM/PM')] = [53    ("%Y", "4-digit year"),54    ("%y", "2-digit year"),55    ("%m", "2-digit month"),56    ("%B", "Full month name"),57    ("%b", "Short month name"),58    ("%d", "2-digit day"),59    ("%A", "Full day name"),60    ("%a", "Short day name"),61    ("%H", "24-hour (00-23)"),62    ("%I", "12-hour (01-12)"),63    ("%M", "Minute"),64    ("%S", "Second"),65    ("%p", "AM/PM")66]
    outputDateTime: 2025-01-29 14:30:45
    ISO formats:
    ISO format: 2025-01-29T14:30:45
    ISO date: 2025-01-29
    ISO time: 14:30:45
    
    Common patterns:
    %Y-%m-%d %H:%M:%S: 2025-01-29 14:30:45
    %m/%d/%Y: 01/29/2025
    %d-%b-%Y: 29-Jan-2025
    %A, %B %d, %Y: Wednesday, January 29, 2025
    
    Time formats:
    24-hour: 14:30:45
    12-hour: 02:30 PM
    
    Date only:
    ISO: 2025-01-29
    US: 01/29/2025
    EU: 29/01/2025
    Full: Wednesday, January 29, 2025
    
    Time only:
    ISO: 14:30:45
    Simple: 14:30
    12-hour: 02:30 PM
    
    Default str():
    Date: 2025-01-29
    Time: 14:30:45
    DateTime: 2025-01-29 14:30:45
    
    Format codes:
  2. for code, description in codes:

    pass 1 of 13
    68for code%Y, description4-digit year in codes[('%Y', '4-digit year'), ('%y', '2-digit year'), ('%m', '2-digit month'), ('%B', 'Full month name'), ('%b', 'Short month name'), ('%d', '2-digit day'), ('%A', 'Full day name'), ('%a', 'Short day name'), ('%H', '24-hour (00-23)'), ('%I', '12-hour (01-12)'), ('%M', 'Minute'), ('%S', 'Second'), ('%p', 'AM/PM')]:69    try:70        value = dt.strftime(code)
    13 passes — pass 1 is the card above
    passcodedescription
    1%Y4-digit year
    2%y2-digit year
    3%m2-digit month
    4%BFull month name
    5%bShort month name
    6%d2-digit day
    7%AFull day name
    8%aShort day name
    9%H24-hour (00-23)
    ⋯ 2 more passes ⋯
    12%SSecond
    13%pAM/PM
  3. value ← 2025

    pass 1 of 13
    68for code, description in codes:69    try:70        value→ 2025 = dt2025-01-29 14:30:45.strftime(code%Y)71        print(f"{code%Y}: {description4-digit year} = {value2025}")72    except:
    output%Y: 4-digit year = 2025
    13 passes — pass 1 is the card above
    passcodedescriptionvalue
    1%Y4-digit year2025
    2%y2-digit year25
    3%m2-digit month01
    4%BFull month nameJanuary
    5%bShort month nameJan
    6%d2-digit day29
    7%AFull day nameWednesday
    8%aShort day nameWed
    9%H24-hour (00-23)14
    ⋯ 2 more passes ⋯
    12%SSecond45
    13%pAM/PMPM
strftime Converting datetime objects to formatted strings with strftime()

Parsing from Strings

iso
parse.py
Replay: real traced execution (multi-file project)
# Parse from string

from datetime import datetime, date, time

# Parse datetime
# Parse ISO format
iso = "2025-01-29T14:30:45"
dt1 = datetime.fromisoformat(iso)
print("Parsed ISO:", dt1)

# Parse with custom pattern
custom1 = "29/01/2025 14:30"
dt2 = datetime.strptime(custom1, "%d/%m/%Y %H:%M")
print("Parsed", custom1, ":", dt2)

# Parse various formats
print("\nParse various formats:")

datetime_strings = [
    ("2025-01-29 14:30:45", "%Y-%m-%d %H:%M:%S"),
    ("01/29/2025 02:30 PM", "%m/%d/%Y %I:%M %p"),
    ("29-Jan-2025 14:30", "%d-%b-%Y %H:%M")
]

for dt_str, fmt in datetime_strings:
    dt = datetime.strptime(dt_str, fmt)
    print(f"{dt_str} -> {dt}")

# Parse dates
print("\nParse dates:")
date1 = date.fromisoformat("2025-01-29")
print("ISO date:", date1)

date2 = datetime.strptime("01/29/2025", "%m/%d/%Y").date()
print("US date:", date2)

# Parse times
print("\nParse times:")
time1 = time.fromisoformat("14:30:45")
print("ISO time:", time1)

time2 = datetime.strptime("02:30 PM", "%I:%M %p").time()
print("12-hour time:", time2)

# Handle parse errors
print("\nHandle parse errors:")
test_strings = [
    "2025-01-29T14:30:45",
    "2025-13-01T14:30:45",  # invalid month
    "not-a-datetime"
]

for s in test_strings:
    try:
        dt = datetime.fromisoformat(s)
        print(f"{s} -> {dt}")
    except ValueError:
        print(f"{s} -> ERROR: Invalid format")

# Safe parse helper
def safe_parse_datetime(s, fmt=None):
    """Safely parse datetime string"""
    try:
        if fmt:
            return datetime.strptime(s, fmt)
        else:
            return datetime.fromisoformat(s)
    except ValueError:
        print(f"Invalid datetime: {s}")
        return None

# Test safe parse
print("\nSafe parse:")
print(safe_parse_datetime("2025-01-29T14:30:45"))
print(safe_parse_datetime("invalid"))

# Parse with multiple formats
print("\nTry multiple formats:")
def parse_flexible(s):
    """Try multiple common formats"""
    formats = [
        "%Y-%m-%d",
        "%m/%d/%Y",
        "%d-%b-%Y",
        "%Y-%m-%d %H:%M:%S",
        "%m/%d/%Y %I:%M %p"
    ]

    for fmt in formats:
        try:
            return datetime.strptime(s, fmt)
        except ValueError:
            continue

    # Try ISO format
    try:
        return datetime.fromisoformat(s)
    except ValueError:
        return None

test_dates = [
    "2025-01-29",
    "01/29/2025",
    "29-Jan-2025",
    "2025-01-29 14:30:45",
    "01/29/2025 02:30 PM"
]

for s in test_dates:
    result = parse_flexible(s)
    if result:
        print(f"{s} -> {result}")
    else:
        print(f"{s} -> Could not parse")

# Parse from string

from datetime import datetime, date, time

# Parse datetime
# Parse ISO format
iso = "2024-02-29T09:15:00"
dt1 = datetime.fromisoformat(iso)
print("Parsed ISO:", dt1)

# Parse with custom pattern
custom1 = "29/01/2025 14:30"
dt2 = datetime.strptime(custom1, "%d/%m/%Y %H:%M")
print("Parsed", custom1, ":", dt2)

# Parse various formats
print("\nParse various formats:")

datetime_strings = [
    ("2025-01-29 14:30:45", "%Y-%m-%d %H:%M:%S"),
    ("01/29/2025 02:30 PM", "%m/%d/%Y %I:%M %p"),
    ("29-Jan-2025 14:30", "%d-%b-%Y %H:%M")
]

for dt_str, fmt in datetime_strings:
    dt = datetime.strptime(dt_str, fmt)
    print(f"{dt_str} -> {dt}")

# Parse dates
print("\nParse dates:")
date1 = date.fromisoformat("2025-01-29")
print("ISO date:", date1)

date2 = datetime.strptime("01/29/2025", "%m/%d/%Y").date()
print("US date:", date2)

# Parse times
print("\nParse times:")
time1 = time.fromisoformat("14:30:45")
print("ISO time:", time1)

time2 = datetime.strptime("02:30 PM", "%I:%M %p").time()
print("12-hour time:", time2)

# Handle parse errors
print("\nHandle parse errors:")
test_strings = [
    "2025-01-29T14:30:45",
    "2025-13-01T14:30:45",  # invalid month
    "not-a-datetime"
]

for s in test_strings:
    try:
        dt = datetime.fromisoformat(s)
        print(f"{s} -> {dt}")
    except ValueError:
        print(f"{s} -> ERROR: Invalid format")

# Safe parse helper
def safe_parse_datetime(s, fmt=None):
    """Safely parse datetime string"""
    try:
        if fmt:
            return datetime.strptime(s, fmt)
        else:
            return datetime.fromisoformat(s)
    except ValueError:
        print(f"Invalid datetime: {s}")
        return None

# Test safe parse
print("\nSafe parse:")
print(safe_parse_datetime("2025-01-29T14:30:45"))
print(safe_parse_datetime("invalid"))

# Parse with multiple formats
print("\nTry multiple formats:")
def parse_flexible(s):
    """Try multiple common formats"""
    formats = [
        "%Y-%m-%d",
        "%m/%d/%Y",
        "%d-%b-%Y",
        "%Y-%m-%d %H:%M:%S",
        "%m/%d/%Y %I:%M %p"
    ]

    for fmt in formats:
        try:
            return datetime.strptime(s, fmt)
        except ValueError:
            continue

    # Try ISO format
    try:
        return datetime.fromisoformat(s)
    except ValueError:
        return None

test_dates = [
    "2025-01-29",
    "01/29/2025",
    "29-Jan-2025",
    "2025-01-29 14:30:45",
    "01/29/2025 02:30 PM"
]

for s in test_dates:
    result = parse_flexible(s)
    if result:
        print(f"{s} -> {result}")
    else:
        print(f"{s} -> Could not parse")

# Parse from string

from datetime import datetime, date, time

# Parse datetime
# Parse ISO format
iso = "2026-06-15T18:45:30"
dt1 = datetime.fromisoformat(iso)
print("Parsed ISO:", dt1)

# Parse with custom pattern
custom1 = "29/01/2025 14:30"
dt2 = datetime.strptime(custom1, "%d/%m/%Y %H:%M")
print("Parsed", custom1, ":", dt2)

# Parse various formats
print("\nParse various formats:")

datetime_strings = [
    ("2025-01-29 14:30:45", "%Y-%m-%d %H:%M:%S"),
    ("01/29/2025 02:30 PM", "%m/%d/%Y %I:%M %p"),
    ("29-Jan-2025 14:30", "%d-%b-%Y %H:%M")
]

for dt_str, fmt in datetime_strings:
    dt = datetime.strptime(dt_str, fmt)
    print(f"{dt_str} -> {dt}")

# Parse dates
print("\nParse dates:")
date1 = date.fromisoformat("2025-01-29")
print("ISO date:", date1)

date2 = datetime.strptime("01/29/2025", "%m/%d/%Y").date()
print("US date:", date2)

# Parse times
print("\nParse times:")
time1 = time.fromisoformat("14:30:45")
print("ISO time:", time1)

time2 = datetime.strptime("02:30 PM", "%I:%M %p").time()
print("12-hour time:", time2)

# Handle parse errors
print("\nHandle parse errors:")
test_strings = [
    "2025-01-29T14:30:45",
    "2025-13-01T14:30:45",  # invalid month
    "not-a-datetime"
]

for s in test_strings:
    try:
        dt = datetime.fromisoformat(s)
        print(f"{s} -> {dt}")
    except ValueError:
        print(f"{s} -> ERROR: Invalid format")

# Safe parse helper
def safe_parse_datetime(s, fmt=None):
    """Safely parse datetime string"""
    try:
        if fmt:
            return datetime.strptime(s, fmt)
        else:
            return datetime.fromisoformat(s)
    except ValueError:
        print(f"Invalid datetime: {s}")
        return None

# Test safe parse
print("\nSafe parse:")
print(safe_parse_datetime("2025-01-29T14:30:45"))
print(safe_parse_datetime("invalid"))

# Parse with multiple formats
print("\nTry multiple formats:")
def parse_flexible(s):
    """Try multiple common formats"""
    formats = [
        "%Y-%m-%d",
        "%m/%d/%Y",
        "%d-%b-%Y",
        "%Y-%m-%d %H:%M:%S",
        "%m/%d/%Y %I:%M %p"
    ]

    for fmt in formats:
        try:
            return datetime.strptime(s, fmt)
        except ValueError:
            continue

    # Try ISO format
    try:
        return datetime.fromisoformat(s)
    except ValueError:
        return None

test_dates = [
    "2025-01-29",
    "01/29/2025",
    "29-Jan-2025",
    "2025-01-29 14:30:45",
    "01/29/2025 02:30 PM"
]

for s in test_dates:
    result = parse_flexible(s)
    if result:
        print(f"{s} -> {result}")
    else:
        print(f"{s} -> Could not parse")

  1. iso ← 2025-01-29T14:30:45, dt1 ← 2025-01-29 14:30:45, custom1 ← 29/01/2025 14:30

    6# Parse ISO format7iso→ 2025-01-29T14:30:45 = "2025-01-29T14:30:45"  #@iso="2024-02-29T09:15:00", "2026-06-15T18:45:30"8dt1→ 2025-01-29 14:30:45 = datetime<class 'datetime.datetime'>.fromisoformat(iso2025-01-29T14:30:45)9print("Parsed ISO:", dt12025-01-29 14:30:45)1011# Parse with custom pattern12custom1→ 29/01/2025 14:30 = "29/01/2025 14:30"13dt2→ 2025-01-29 14:30:00 = datetime<class 'datetime.datetime'>.strptime(custom129/01/2025 14:30, "%d/%m/%Y %H:%M")14print("Parsed", custom129/01/2025 14:30, ":", dt22025-01-29 14:30:00)1516# Parse various formats17print("\nParse various formats:")1819datetime_strings→ [('2025-01-29 14:30:45', '%Y-%m-%d %H:%M:%S'), ('01/29/2025 02:30 PM', '%m/%d/%Y %I:%M %p'), ('29-Jan-2025 14:30', '%d-%b-%Y %H:%M')] = [20    ("2025-01-29 14:30:45", "%Y-%m-%d %H:%M:%S"),21    ("01/29/2025 02:30 PM", "%m/%d/%Y %I:%M %p"),22    ("29-Jan-2025 14:30", "%d-%b-%Y %H:%M")23]
    outputParsed ISO: 2025-01-29 14:30:45
    Parsed 29/01/2025 14:30 : 2025-01-29 14:30:00
    
    Parse various formats:
  2. dt ← 2025-01-29 14:30:45

    pass 1 of 3
    25for dt_str2025-01-29 14:30:45, fmt%Y-%m-%d %H:%M:%S in datetime_strings[('2025-01-29 14:30:45', '%Y-%m-%d %H:%M:%S'), ('01/29/2025 02:30 PM', '%m/%d/%Y %I:%M %p'), ('29-Jan-2025 14:30', '%d-%b-%Y %H:%M')]:26    dt→ 2025-01-29 14:30:45 = datetime<class 'datetime.datetime'>.strptime(dt_str2025-01-29 14:30:45, fmt%Y-%m-%d %H:%M:%S)27    print(f"{dt_str2025-01-29 14:30:45} -> {dt2025-01-29 14:30:45}")
    output2025-01-29 14:30:45 -> 2025-01-29 14:30:45
    All 3 passes — pass 1 is the card above
    passdt_strfmtdt
    12025-01-29 14:30:45%Y-%m-%d %H:%M:%S2025-01-29 14:30:45
    201/29/2025 02:30 PM%m/%d/%Y %I:%M %p2025-01-29 14:30:00
    329-Jan-2025 14:30%d-%b-%Y %H:%M2025-01-29 14:30:00
  3. date1 ← 2025-01-29, date2 ← 2025-01-29, time1 ← 14:30:45, time2 ← 14:30:00

    29# Parse dates30print("\nParse dates:")31date1→ 2025-01-29 = date<class 'datetime.date'>.fromisoformat("2025-01-29")32print("ISO date:", date12025-01-29)3334date2→ 2025-01-29 = datetime<class 'datetime.datetime'>.strptime("01/29/2025", "%m/%d/%Y").date()35print("US date:", date22025-01-29)3637# Parse times38print("\nParse times:")39time1→ 14:30:45 = time<class 'datetime.time'>.fromisoformat("14:30:45")40print("ISO time:", time114:30:45)4142time2→ 14:30:00 = datetime<class 'datetime.datetime'>.strptime("02:30 PM", "%I:%M %p").time()43print("12-hour time:", time214:30:00)4445# Handle parse errors46print("\nHandle parse errors:")47test_strings→ ['2025-01-29T14:30:45', '2025-13-01T14:30:45', 'not-a-datetime'] = [48    "2025-01-29T14:30:45",49    "2025-13-01T14:30:45",  # invalid month50    "not-a-datetime"51]
    output
    Parse dates:
    ISO date: 2025-01-29
    US date: 2025-01-29
    
    Parse times:
    ISO time: 14:30:45
    12-hour time: 14:30:00
    
    Handle parse errors:
  4. for s in test_strings:

    pass 1 of 3
    53for s2025-01-29T14:30:45 in test_strings['2025-01-29T14:30:45', '2025-13-01T14:30:45', 'not-a-datetime']:54    try:55        dt = datetime.fromisoformat(s)
    All 3 passes — pass 1 is the card above
    passs
    12025-01-29T14:30:45
    22025-13-01T14:30:45
    3not-a-datetime
  5. dt ← 2025-01-29 14:30:45

    pass 1 of 3
    53for s in test_strings:54    try:55        dt→ 2025-01-29 14:30:45 = datetime<class 'datetime.datetime'>.fromisoformat(s2025-01-29T14:30:45)56        print(f"{s2025-01-29T14:30:45} -> {dt2025-01-29 14:30:45}")57    except ValueError:
    output2025-01-29T14:30:45 -> 2025-01-29 14:30:45
    All 3 passes — pass 1 is the card above
    passsdt
    12025-01-29T14:30:452025-01-29 14:30:45
    22025-13-01T14:30:45
    3not-a-datetime
  6. except ValueError:

    pass 1 of 2
    56    print(f"{s} -> {dt}")57except ValueError:58    print(f"{s2025-13-01T14:30:45} -> ERROR: Invalid format")
    output2025-13-01T14:30:45 -> ERROR: Invalid format
    2025-13-01T14:30:45 -> ERROR: Invalid format
  7. except ValueError:

    pass 2 of 2
    56    print(f"{s} -> {dt}")57except ValueError:58    print(f"{snot-a-datetime} -> ERROR: Invalid format")
    outputnot-a-datetime -> ERROR: Invalid format
    not-a-datetime -> ERROR: Invalid format
  8. print(" Safe parse:")

    72# Test safe parse73print("\nSafe parse:")74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))
    output
    Safe parse:
  9. def safe_parse_datetime(s, fmt=None):

    pass 1 of 2
    60# Safe parse helper61def safe_parse_datetime(s2025-01-29T14:30:45, fmtNone=NoneNone):62    """Safely parse datetime string"""63    try:
  10. else:

    pass 1 of 2
    64    if fmt:65        return datetime.strptime(s, fmt)66    else:67        return datetime<class 'datetime.datetime'>.fromisoformat(s2025-01-29T14:30:45)68except ValueError:
  11. print(safe_parse_datetime("2025-01-29T14:30:45"))

    73print("\nSafe parse:")74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))
    output2025-01-29 14:30:45
  12. def safe_parse_datetime(s, fmt=None):

    pass 2 of 2
    60# Safe parse helper61def safe_parse_datetime(sinvalid, fmtNone=NoneNone):62    """Safely parse datetime string"""63    try:
  13. else:

    pass 2 of 2
    64    if fmt:65        return datetime.strptime(s, fmt)66    else:67        return datetime<class 'datetime.datetime'>.fromisoformat(sinvalid)68except ValueError:
  14. except ValueError:

    67        return datetime.fromisoformat(s)68except ValueError:69    print(f"Invalid datetime: {sinvalid}")70    return None
    outputInvalid datetime: invalid
  15. test_dates ← ['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM']

    74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))7677# Parse with multiple formats78print("\nTry multiple formats:")79def parse_flexible(s):80    """Try multiple common formats"""81    formats = [82        "%Y-%m-%d",83        "%m/%d/%Y",84        "%d-%b-%Y",85        "%Y-%m-%d %H:%M:%S",86        "%m/%d/%Y %I:%M %p"87    ]88    89    for fmt in formats:90        try:91            return datetime.strptime(s, fmt)92        except ValueError:93            continue94    95    # Try ISO format96    try:97        return datetime.fromisoformat(s)98    except ValueError:99        return None100101test_dates→ ['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM'] = [102    "2025-01-29",103    "01/29/2025",104    "29-Jan-2025",105    "2025-01-29 14:30:45",106    "01/29/2025 02:30 PM"107]
    outputNone
    
    Try multiple formats:
  16. for s in test_dates:

    pass 1 of 5
    109for s2025-01-29 in test_dates['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM']:110    result = parse_flexible(s2025-01-29)111    if result:
    All 5 passes — pass 1 is the card above
    passs
    12025-01-29
    201/29/2025
    329-Jan-2025
    42025-01-29 14:30:45
    501/29/2025 02:30 PM
  17. formats ← ['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']

    pass 1 of 5
    78print("\nTry multiple formats:")79def parse_flexible(s2025-01-29):80    """Try multiple common formats"""81    formats→ ['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p'] = [82        "%Y-%m-%d",83        "%m/%d/%Y",84        "%d-%b-%Y",85        "%Y-%m-%d %H:%M:%S",86        "%m/%d/%Y %I:%M %p"87    ]
    All 5 passes — pass 1 is the card above
    passsformats
    12025-01-29['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    201/29/2025['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    329-Jan-2025['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    42025-01-29 14:30:45['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    501/29/2025 02:30 PM['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
  18. for fmt in formats:

    pass 1 of 15
    89for fmt%Y-%m-%d in formats['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']:90    try:91        return datetime.strptime(s, fmt)
    15 passes — pass 1 is the card above
    passfmt
    1%Y-%m-%d
    2%Y-%m-%d
    3%m/%d/%Y
    4%Y-%m-%d
    5%m/%d/%Y
    6%d-%b-%Y
    7%Y-%m-%d
    8%m/%d/%Y
    9%d-%b-%Y
    ⋯ 4 more passes ⋯
    14%Y-%m-%d %H:%M:%S
    15%m/%d/%Y %I:%M %p
  19. try:

    pass 1 of 15
    89for fmt in formats:90    try:91        return datetime<class 'datetime.datetime'>.strptime(s2025-01-29, fmt%Y-%m-%d)92    except ValueError:
    15 passes — pass 1 is the card above
    passsfmt
    12025-01-29%Y-%m-%d
    201/29/2025%Y-%m-%d
    301/29/2025%m/%d/%Y
    429-Jan-2025%Y-%m-%d
    529-Jan-2025%m/%d/%Y
    629-Jan-2025%d-%b-%Y
    72025-01-29 14:30:45%Y-%m-%d
    82025-01-29 14:30:45%m/%d/%Y
    92025-01-29 14:30:45%d-%b-%Y
    ⋯ 4 more passes ⋯
    1401/29/2025 02:30 PM%Y-%m-%d %H:%M:%S
    1501/29/2025 02:30 PM%m/%d/%Y %I:%M %p
  20. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s2025-01-29)111    if result:
  21. if result:

    pass 1 of 5
    110result = parse_flexible(s)111if result2025-01-29 00:00:00:112    print(f"{s2025-01-29} -> {result2025-01-29 00:00:00}")113else:
    output2025-01-29 -> 2025-01-29 00:00:00
    All 5 passes — pass 1 is the card above
    passresults
    12025-01-29 00:00:002025-01-29
    22025-01-29 00:00:0001/29/2025
    32025-01-29 00:00:0029-Jan-2025
    42025-01-29 14:30:452025-01-29 14:30:45
    52025-01-29 14:30:0001/29/2025 02:30 PM
  22. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s01/29/2025)111    if result:
  23. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s29-Jan-2025)111    if result:
  24. result ← 2025-01-29 14:30:45

    109for s in test_dates:110    result→ 2025-01-29 14:30:45 = parse_flexible(s2025-01-29 14:30:45)111    if result:
  25. result ← 2025-01-29 14:30:00

    109for s in test_dates:110    result→ 2025-01-29 14:30:00 = parse_flexible(s01/29/2025 02:30 PM)111    if result:
  1. iso ← 2024-02-29T09:15:00, dt1 ← 2024-02-29 09:15:00, custom1 ← 29/01/2025 14:30

    6# Parse ISO format7iso→ 2024-02-29T09:15:00 = "2024-02-29T09:15:00"8dt1→ 2024-02-29 09:15:00 = datetime<class 'datetime.datetime'>.fromisoformat(iso2024-02-29T09:15:00)9print("Parsed ISO:", dt12024-02-29 09:15:00)1011# Parse with custom pattern12custom1→ 29/01/2025 14:30 = "29/01/2025 14:30"13dt2→ 2025-01-29 14:30:00 = datetime<class 'datetime.datetime'>.strptime(custom129/01/2025 14:30, "%d/%m/%Y %H:%M")14print("Parsed", custom129/01/2025 14:30, ":", dt22025-01-29 14:30:00)1516# Parse various formats17print("\nParse various formats:")1819datetime_strings→ [('2025-01-29 14:30:45', '%Y-%m-%d %H:%M:%S'), ('01/29/2025 02:30 PM', '%m/%d/%Y %I:%M %p'), ('29-Jan-2025 14:30', '%d-%b-%Y %H:%M')] = [20    ("2025-01-29 14:30:45", "%Y-%m-%d %H:%M:%S"),21    ("01/29/2025 02:30 PM", "%m/%d/%Y %I:%M %p"),22    ("29-Jan-2025 14:30", "%d-%b-%Y %H:%M")23]
    outputParsed ISO: 2024-02-29 09:15:00
    Parsed 29/01/2025 14:30 : 2025-01-29 14:30:00
    
    Parse various formats:
  2. dt ← 2025-01-29 14:30:45

    pass 1 of 3
    25for dt_str2025-01-29 14:30:45, fmt%Y-%m-%d %H:%M:%S in datetime_strings[('2025-01-29 14:30:45', '%Y-%m-%d %H:%M:%S'), ('01/29/2025 02:30 PM', '%m/%d/%Y %I:%M %p'), ('29-Jan-2025 14:30', '%d-%b-%Y %H:%M')]:26    dt→ 2025-01-29 14:30:45 = datetime<class 'datetime.datetime'>.strptime(dt_str2025-01-29 14:30:45, fmt%Y-%m-%d %H:%M:%S)27    print(f"{dt_str2025-01-29 14:30:45} -> {dt2025-01-29 14:30:45}")
    output2025-01-29 14:30:45 -> 2025-01-29 14:30:45
    All 3 passes — pass 1 is the card above
    passdt_strfmtdt
    12025-01-29 14:30:45%Y-%m-%d %H:%M:%S2025-01-29 14:30:45
    201/29/2025 02:30 PM%m/%d/%Y %I:%M %p2025-01-29 14:30:00
    329-Jan-2025 14:30%d-%b-%Y %H:%M2025-01-29 14:30:00
  3. date1 ← 2025-01-29, date2 ← 2025-01-29, time1 ← 14:30:45, time2 ← 14:30:00

    29# Parse dates30print("\nParse dates:")31date1→ 2025-01-29 = date<class 'datetime.date'>.fromisoformat("2025-01-29")32print("ISO date:", date12025-01-29)3334date2→ 2025-01-29 = datetime<class 'datetime.datetime'>.strptime("01/29/2025", "%m/%d/%Y").date()35print("US date:", date22025-01-29)3637# Parse times38print("\nParse times:")39time1→ 14:30:45 = time<class 'datetime.time'>.fromisoformat("14:30:45")40print("ISO time:", time114:30:45)4142time2→ 14:30:00 = datetime<class 'datetime.datetime'>.strptime("02:30 PM", "%I:%M %p").time()43print("12-hour time:", time214:30:00)4445# Handle parse errors46print("\nHandle parse errors:")47test_strings→ ['2025-01-29T14:30:45', '2025-13-01T14:30:45', 'not-a-datetime'] = [48    "2025-01-29T14:30:45",49    "2025-13-01T14:30:45",  # invalid month50    "not-a-datetime"51]
    output
    Parse dates:
    ISO date: 2025-01-29
    US date: 2025-01-29
    
    Parse times:
    ISO time: 14:30:45
    12-hour time: 14:30:00
    
    Handle parse errors:
  4. for s in test_strings:

    pass 1 of 3
    53for s2025-01-29T14:30:45 in test_strings['2025-01-29T14:30:45', '2025-13-01T14:30:45', 'not-a-datetime']:54    try:55        dt = datetime.fromisoformat(s)
    All 3 passes — pass 1 is the card above
    passs
    12025-01-29T14:30:45
    22025-13-01T14:30:45
    3not-a-datetime
  5. dt ← 2025-01-29 14:30:45

    pass 1 of 3
    53for s in test_strings:54    try:55        dt→ 2025-01-29 14:30:45 = datetime<class 'datetime.datetime'>.fromisoformat(s2025-01-29T14:30:45)56        print(f"{s2025-01-29T14:30:45} -> {dt2025-01-29 14:30:45}")57    except ValueError:
    output2025-01-29T14:30:45 -> 2025-01-29 14:30:45
    All 3 passes — pass 1 is the card above
    passsdt
    12025-01-29T14:30:452025-01-29 14:30:45
    22025-13-01T14:30:45
    3not-a-datetime
  6. except ValueError:

    pass 1 of 2
    56    print(f"{s} -> {dt}")57except ValueError:58    print(f"{s2025-13-01T14:30:45} -> ERROR: Invalid format")
    output2025-13-01T14:30:45 -> ERROR: Invalid format
    2025-13-01T14:30:45 -> ERROR: Invalid format
  7. except ValueError:

    pass 2 of 2
    56    print(f"{s} -> {dt}")57except ValueError:58    print(f"{snot-a-datetime} -> ERROR: Invalid format")
    outputnot-a-datetime -> ERROR: Invalid format
    not-a-datetime -> ERROR: Invalid format
  8. print(" Safe parse:")

    72# Test safe parse73print("\nSafe parse:")74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))
    output
    Safe parse:
  9. def safe_parse_datetime(s, fmt=None):

    pass 1 of 2
    60# Safe parse helper61def safe_parse_datetime(s2025-01-29T14:30:45, fmtNone=NoneNone):62    """Safely parse datetime string"""63    try:
  10. else:

    pass 1 of 2
    64    if fmt:65        return datetime.strptime(s, fmt)66    else:67        return datetime<class 'datetime.datetime'>.fromisoformat(s2025-01-29T14:30:45)68except ValueError:
  11. print(safe_parse_datetime("2025-01-29T14:30:45"))

    73print("\nSafe parse:")74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))
    output2025-01-29 14:30:45
  12. def safe_parse_datetime(s, fmt=None):

    pass 2 of 2
    60# Safe parse helper61def safe_parse_datetime(sinvalid, fmtNone=NoneNone):62    """Safely parse datetime string"""63    try:
  13. else:

    pass 2 of 2
    64    if fmt:65        return datetime.strptime(s, fmt)66    else:67        return datetime<class 'datetime.datetime'>.fromisoformat(sinvalid)68except ValueError:
  14. except ValueError:

    67        return datetime.fromisoformat(s)68except ValueError:69    print(f"Invalid datetime: {sinvalid}")70    return None
    outputInvalid datetime: invalid
  15. test_dates ← ['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM']

    74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))7677# Parse with multiple formats78print("\nTry multiple formats:")79def parse_flexible(s):80    """Try multiple common formats"""81    formats = [82        "%Y-%m-%d",83        "%m/%d/%Y",84        "%d-%b-%Y",85        "%Y-%m-%d %H:%M:%S",86        "%m/%d/%Y %I:%M %p"87    ]88    89    for fmt in formats:90        try:91            return datetime.strptime(s, fmt)92        except ValueError:93            continue94    95    # Try ISO format96    try:97        return datetime.fromisoformat(s)98    except ValueError:99        return None100101test_dates→ ['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM'] = [102    "2025-01-29",103    "01/29/2025",104    "29-Jan-2025",105    "2025-01-29 14:30:45",106    "01/29/2025 02:30 PM"107]
    outputNone
    
    Try multiple formats:
  16. for s in test_dates:

    pass 1 of 5
    109for s2025-01-29 in test_dates['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM']:110    result = parse_flexible(s2025-01-29)111    if result:
    All 5 passes — pass 1 is the card above
    passs
    12025-01-29
    201/29/2025
    329-Jan-2025
    42025-01-29 14:30:45
    501/29/2025 02:30 PM
  17. formats ← ['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']

    pass 1 of 5
    78print("\nTry multiple formats:")79def parse_flexible(s2025-01-29):80    """Try multiple common formats"""81    formats→ ['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p'] = [82        "%Y-%m-%d",83        "%m/%d/%Y",84        "%d-%b-%Y",85        "%Y-%m-%d %H:%M:%S",86        "%m/%d/%Y %I:%M %p"87    ]
    All 5 passes — pass 1 is the card above
    passsformats
    12025-01-29['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    201/29/2025['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    329-Jan-2025['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    42025-01-29 14:30:45['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    501/29/2025 02:30 PM['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
  18. for fmt in formats:

    pass 1 of 15
    89for fmt%Y-%m-%d in formats['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']:90    try:91        return datetime.strptime(s, fmt)
    15 passes — pass 1 is the card above
    passfmt
    1%Y-%m-%d
    2%Y-%m-%d
    3%m/%d/%Y
    4%Y-%m-%d
    5%m/%d/%Y
    6%d-%b-%Y
    7%Y-%m-%d
    8%m/%d/%Y
    9%d-%b-%Y
    ⋯ 4 more passes ⋯
    14%Y-%m-%d %H:%M:%S
    15%m/%d/%Y %I:%M %p
  19. try:

    pass 1 of 15
    89for fmt in formats:90    try:91        return datetime<class 'datetime.datetime'>.strptime(s2025-01-29, fmt%Y-%m-%d)92    except ValueError:
    15 passes — pass 1 is the card above
    passsfmt
    12025-01-29%Y-%m-%d
    201/29/2025%Y-%m-%d
    301/29/2025%m/%d/%Y
    429-Jan-2025%Y-%m-%d
    529-Jan-2025%m/%d/%Y
    629-Jan-2025%d-%b-%Y
    72025-01-29 14:30:45%Y-%m-%d
    82025-01-29 14:30:45%m/%d/%Y
    92025-01-29 14:30:45%d-%b-%Y
    ⋯ 4 more passes ⋯
    1401/29/2025 02:30 PM%Y-%m-%d %H:%M:%S
    1501/29/2025 02:30 PM%m/%d/%Y %I:%M %p
  20. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s2025-01-29)111    if result:
  21. if result:

    pass 1 of 5
    110result = parse_flexible(s)111if result2025-01-29 00:00:00:112    print(f"{s2025-01-29} -> {result2025-01-29 00:00:00}")113else:
    output2025-01-29 -> 2025-01-29 00:00:00
    All 5 passes — pass 1 is the card above
    passresults
    12025-01-29 00:00:002025-01-29
    22025-01-29 00:00:0001/29/2025
    32025-01-29 00:00:0029-Jan-2025
    42025-01-29 14:30:452025-01-29 14:30:45
    52025-01-29 14:30:0001/29/2025 02:30 PM
  22. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s01/29/2025)111    if result:
  23. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s29-Jan-2025)111    if result:
  24. result ← 2025-01-29 14:30:45

    109for s in test_dates:110    result→ 2025-01-29 14:30:45 = parse_flexible(s2025-01-29 14:30:45)111    if result:
  25. result ← 2025-01-29 14:30:00

    109for s in test_dates:110    result→ 2025-01-29 14:30:00 = parse_flexible(s01/29/2025 02:30 PM)111    if result:
  1. iso ← 2026-06-15T18:45:30, dt1 ← 2026-06-15 18:45:30, custom1 ← 29/01/2025 14:30

    6# Parse ISO format7iso→ 2026-06-15T18:45:30 = "2026-06-15T18:45:30"8dt1→ 2026-06-15 18:45:30 = datetime<class 'datetime.datetime'>.fromisoformat(iso2026-06-15T18:45:30)9print("Parsed ISO:", dt12026-06-15 18:45:30)1011# Parse with custom pattern12custom1→ 29/01/2025 14:30 = "29/01/2025 14:30"13dt2→ 2025-01-29 14:30:00 = datetime<class 'datetime.datetime'>.strptime(custom129/01/2025 14:30, "%d/%m/%Y %H:%M")14print("Parsed", custom129/01/2025 14:30, ":", dt22025-01-29 14:30:00)1516# Parse various formats17print("\nParse various formats:")1819datetime_strings→ [('2025-01-29 14:30:45', '%Y-%m-%d %H:%M:%S'), ('01/29/2025 02:30 PM', '%m/%d/%Y %I:%M %p'), ('29-Jan-2025 14:30', '%d-%b-%Y %H:%M')] = [20    ("2025-01-29 14:30:45", "%Y-%m-%d %H:%M:%S"),21    ("01/29/2025 02:30 PM", "%m/%d/%Y %I:%M %p"),22    ("29-Jan-2025 14:30", "%d-%b-%Y %H:%M")23]
    outputParsed ISO: 2026-06-15 18:45:30
    Parsed 29/01/2025 14:30 : 2025-01-29 14:30:00
    
    Parse various formats:
  2. dt ← 2025-01-29 14:30:45

    pass 1 of 3
    25for dt_str2025-01-29 14:30:45, fmt%Y-%m-%d %H:%M:%S in datetime_strings[('2025-01-29 14:30:45', '%Y-%m-%d %H:%M:%S'), ('01/29/2025 02:30 PM', '%m/%d/%Y %I:%M %p'), ('29-Jan-2025 14:30', '%d-%b-%Y %H:%M')]:26    dt→ 2025-01-29 14:30:45 = datetime<class 'datetime.datetime'>.strptime(dt_str2025-01-29 14:30:45, fmt%Y-%m-%d %H:%M:%S)27    print(f"{dt_str2025-01-29 14:30:45} -> {dt2025-01-29 14:30:45}")
    output2025-01-29 14:30:45 -> 2025-01-29 14:30:45
    All 3 passes — pass 1 is the card above
    passdt_strfmtdt
    12025-01-29 14:30:45%Y-%m-%d %H:%M:%S2025-01-29 14:30:45
    201/29/2025 02:30 PM%m/%d/%Y %I:%M %p2025-01-29 14:30:00
    329-Jan-2025 14:30%d-%b-%Y %H:%M2025-01-29 14:30:00
  3. date1 ← 2025-01-29, date2 ← 2025-01-29, time1 ← 14:30:45, time2 ← 14:30:00

    29# Parse dates30print("\nParse dates:")31date1→ 2025-01-29 = date<class 'datetime.date'>.fromisoformat("2025-01-29")32print("ISO date:", date12025-01-29)3334date2→ 2025-01-29 = datetime<class 'datetime.datetime'>.strptime("01/29/2025", "%m/%d/%Y").date()35print("US date:", date22025-01-29)3637# Parse times38print("\nParse times:")39time1→ 14:30:45 = time<class 'datetime.time'>.fromisoformat("14:30:45")40print("ISO time:", time114:30:45)4142time2→ 14:30:00 = datetime<class 'datetime.datetime'>.strptime("02:30 PM", "%I:%M %p").time()43print("12-hour time:", time214:30:00)4445# Handle parse errors46print("\nHandle parse errors:")47test_strings→ ['2025-01-29T14:30:45', '2025-13-01T14:30:45', 'not-a-datetime'] = [48    "2025-01-29T14:30:45",49    "2025-13-01T14:30:45",  # invalid month50    "not-a-datetime"51]
    output
    Parse dates:
    ISO date: 2025-01-29
    US date: 2025-01-29
    
    Parse times:
    ISO time: 14:30:45
    12-hour time: 14:30:00
    
    Handle parse errors:
  4. for s in test_strings:

    pass 1 of 3
    53for s2025-01-29T14:30:45 in test_strings['2025-01-29T14:30:45', '2025-13-01T14:30:45', 'not-a-datetime']:54    try:55        dt = datetime.fromisoformat(s)
    All 3 passes — pass 1 is the card above
    passs
    12025-01-29T14:30:45
    22025-13-01T14:30:45
    3not-a-datetime
  5. dt ← 2025-01-29 14:30:45

    pass 1 of 3
    53for s in test_strings:54    try:55        dt→ 2025-01-29 14:30:45 = datetime<class 'datetime.datetime'>.fromisoformat(s2025-01-29T14:30:45)56        print(f"{s2025-01-29T14:30:45} -> {dt2025-01-29 14:30:45}")57    except ValueError:
    output2025-01-29T14:30:45 -> 2025-01-29 14:30:45
    All 3 passes — pass 1 is the card above
    passsdt
    12025-01-29T14:30:452025-01-29 14:30:45
    22025-13-01T14:30:45
    3not-a-datetime
  6. except ValueError:

    pass 1 of 2
    56    print(f"{s} -> {dt}")57except ValueError:58    print(f"{s2025-13-01T14:30:45} -> ERROR: Invalid format")
    output2025-13-01T14:30:45 -> ERROR: Invalid format
    2025-13-01T14:30:45 -> ERROR: Invalid format
  7. except ValueError:

    pass 2 of 2
    56    print(f"{s} -> {dt}")57except ValueError:58    print(f"{snot-a-datetime} -> ERROR: Invalid format")
    outputnot-a-datetime -> ERROR: Invalid format
    not-a-datetime -> ERROR: Invalid format
  8. print(" Safe parse:")

    72# Test safe parse73print("\nSafe parse:")74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))
    output
    Safe parse:
  9. def safe_parse_datetime(s, fmt=None):

    pass 1 of 2
    60# Safe parse helper61def safe_parse_datetime(s2025-01-29T14:30:45, fmtNone=NoneNone):62    """Safely parse datetime string"""63    try:
  10. else:

    pass 1 of 2
    64    if fmt:65        return datetime.strptime(s, fmt)66    else:67        return datetime<class 'datetime.datetime'>.fromisoformat(s2025-01-29T14:30:45)68except ValueError:
  11. print(safe_parse_datetime("2025-01-29T14:30:45"))

    73print("\nSafe parse:")74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))
    output2025-01-29 14:30:45
  12. def safe_parse_datetime(s, fmt=None):

    pass 2 of 2
    60# Safe parse helper61def safe_parse_datetime(sinvalid, fmtNone=NoneNone):62    """Safely parse datetime string"""63    try:
  13. else:

    pass 2 of 2
    64    if fmt:65        return datetime.strptime(s, fmt)66    else:67        return datetime<class 'datetime.datetime'>.fromisoformat(sinvalid)68except ValueError:
  14. except ValueError:

    67        return datetime.fromisoformat(s)68except ValueError:69    print(f"Invalid datetime: {sinvalid}")70    return None
    outputInvalid datetime: invalid
  15. test_dates ← ['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM']

    74print(safe_parse_datetime("2025-01-29T14:30:45"))75print(safe_parse_datetime("invalid"))7677# Parse with multiple formats78print("\nTry multiple formats:")79def parse_flexible(s):80    """Try multiple common formats"""81    formats = [82        "%Y-%m-%d",83        "%m/%d/%Y",84        "%d-%b-%Y",85        "%Y-%m-%d %H:%M:%S",86        "%m/%d/%Y %I:%M %p"87    ]88    89    for fmt in formats:90        try:91            return datetime.strptime(s, fmt)92        except ValueError:93            continue94    95    # Try ISO format96    try:97        return datetime.fromisoformat(s)98    except ValueError:99        return None100101test_dates→ ['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM'] = [102    "2025-01-29",103    "01/29/2025",104    "29-Jan-2025",105    "2025-01-29 14:30:45",106    "01/29/2025 02:30 PM"107]
    outputNone
    
    Try multiple formats:
  16. for s in test_dates:

    pass 1 of 5
    109for s2025-01-29 in test_dates['2025-01-29', '01/29/2025', '29-Jan-2025', '2025-01-29 14:30:45', '01/29/2025 02:30 PM']:110    result = parse_flexible(s2025-01-29)111    if result:
    All 5 passes — pass 1 is the card above
    passs
    12025-01-29
    201/29/2025
    329-Jan-2025
    42025-01-29 14:30:45
    501/29/2025 02:30 PM
  17. formats ← ['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']

    pass 1 of 5
    78print("\nTry multiple formats:")79def parse_flexible(s2025-01-29):80    """Try multiple common formats"""81    formats→ ['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p'] = [82        "%Y-%m-%d",83        "%m/%d/%Y",84        "%d-%b-%Y",85        "%Y-%m-%d %H:%M:%S",86        "%m/%d/%Y %I:%M %p"87    ]
    All 5 passes — pass 1 is the card above
    passsformats
    12025-01-29['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    201/29/2025['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    329-Jan-2025['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    42025-01-29 14:30:45['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
    501/29/2025 02:30 PM['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']
  18. for fmt in formats:

    pass 1 of 15
    89for fmt%Y-%m-%d in formats['%Y-%m-%d', '%m/%d/%Y', '%d-%b-%Y', '%Y-%m-%d %H:%M:%S', '%m/%d/%Y %I:%M %p']:90    try:91        return datetime.strptime(s, fmt)
    15 passes — pass 1 is the card above
    passfmt
    1%Y-%m-%d
    2%Y-%m-%d
    3%m/%d/%Y
    4%Y-%m-%d
    5%m/%d/%Y
    6%d-%b-%Y
    7%Y-%m-%d
    8%m/%d/%Y
    9%d-%b-%Y
    ⋯ 4 more passes ⋯
    14%Y-%m-%d %H:%M:%S
    15%m/%d/%Y %I:%M %p
  19. try:

    pass 1 of 15
    89for fmt in formats:90    try:91        return datetime<class 'datetime.datetime'>.strptime(s2025-01-29, fmt%Y-%m-%d)92    except ValueError:
    15 passes — pass 1 is the card above
    passsfmt
    12025-01-29%Y-%m-%d
    201/29/2025%Y-%m-%d
    301/29/2025%m/%d/%Y
    429-Jan-2025%Y-%m-%d
    529-Jan-2025%m/%d/%Y
    629-Jan-2025%d-%b-%Y
    72025-01-29 14:30:45%Y-%m-%d
    82025-01-29 14:30:45%m/%d/%Y
    92025-01-29 14:30:45%d-%b-%Y
    ⋯ 4 more passes ⋯
    1401/29/2025 02:30 PM%Y-%m-%d %H:%M:%S
    1501/29/2025 02:30 PM%m/%d/%Y %I:%M %p
  20. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s2025-01-29)111    if result:
  21. if result:

    pass 1 of 5
    110result = parse_flexible(s)111if result2025-01-29 00:00:00:112    print(f"{s2025-01-29} -> {result2025-01-29 00:00:00}")113else:
    output2025-01-29 -> 2025-01-29 00:00:00
    All 5 passes — pass 1 is the card above
    passresults
    12025-01-29 00:00:002025-01-29
    22025-01-29 00:00:0001/29/2025
    32025-01-29 00:00:0029-Jan-2025
    42025-01-29 14:30:452025-01-29 14:30:45
    52025-01-29 14:30:0001/29/2025 02:30 PM
  22. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s01/29/2025)111    if result:
  23. result ← 2025-01-29 00:00:00

    109for s in test_dates:110    result→ 2025-01-29 00:00:00 = parse_flexible(s29-Jan-2025)111    if result:
  24. result ← 2025-01-29 14:30:45

    109for s in test_dates:110    result→ 2025-01-29 14:30:45 = parse_flexible(s2025-01-29 14:30:45)111    if result:
  25. result ← 2025-01-29 14:30:00

    109for s in test_dates:110    result→ 2025-01-29 14:30:00 = parse_flexible(s01/29/2025 02:30 PM)111    if result:
strptime Converting strings to datetime objects with strptime()

ISO Format

iso.py
Replay: real traced execution (multi-file project)
# ISO format

from datetime import datetime, date, time, timezone

# ISO 8601 formats
dt = datetime(2025, 1, 29, 14, 30, 45)
d = dt.date()
t = dt.time()

# ISO date
print("ISO Date formats:")
print("isoformat():", d.isoformat())
print("ISO string:", str(d))

# ISO time
print("\nISO Time formats:")
print("isoformat():", t.isoformat())
print("ISO string:", str(t))

# ISO datetime
print("\nISO DateTime formats:")
print("isoformat():", dt.isoformat())
print("ISO with T:", dt.isoformat(sep='T'))
print("ISO with space:", dt.isoformat(sep=' '))

# With timezone
dt_utc = datetime.now(timezone.utc).replace(
    year=2025, month=1, day=15, hour=10, minute=30, second=0, microsecond=0
)
print("\nWith timezone:")
print("UTC datetime:", dt_utc.isoformat())

# With microseconds
dt_micro = datetime(2025, 1, 29, 14, 30, 45, 123456)
print("\nWith microseconds:")
print("Full precision:", dt_micro.isoformat())
print("Truncated:", dt_micro.isoformat(timespec='seconds'))

# Different time specifications
print("\nTime specifications:")
for spec in ['auto', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds']:
    print(f"{spec:15}: {dt_micro.isoformat(timespec=spec)}")

# Parse ISO formats
print("\nParse ISO formats:")

iso_date = "2025-01-29"
parsed_date = date.fromisoformat(iso_date)
print(f"Date: {iso_date} -> {parsed_date}")

iso_time = "14:30:45"
parsed_time = time.fromisoformat(iso_time)
print(f"Time: {iso_time} -> {parsed_time}")

iso_datetime = "2025-01-29T14:30:45"
parsed_dt = datetime.fromisoformat(iso_datetime)
print(f"DateTime: {iso_datetime} -> {parsed_dt}")

# Compact formats
print("\nCompact formats:")
compact = dt.strftime("%Y%m%d")
print("Date compact:", compact)
compact_time = dt.strftime("%Y%m%dT%H%M%S")
print("DateTime compact:", compact_time)

# ISO week date
print("\nISO week date:")
iso_calendar = d.isocalendar()
print(f"Year: {iso_calendar.year}")
print(f"Week: {iso_calendar.week}")
print(f"Weekday: {iso_calendar.weekday}")
print(f"ISO week: {iso_calendar.year}-W{iso_calendar.week:02d}-{iso_calendar.weekday}")

# Round-trip conversion
print("\nRound-trip:")
original = datetime.now().replace(
    year=2025, month=1, day=15, hour=10, minute=30, second=0, microsecond=0
)
iso_str = original.isoformat()
parsed = datetime.fromisoformat(iso_str)
print(f"Original: {original}")
print(f"ISO string: {iso_str}")
print(f"Parsed: {parsed}")
print(f"Equal: {original == parsed}")

# Different separators
print("\nDifferent separators:")
print("T separator:", dt.isoformat(sep='T'))
print("Space separator:", dt.isoformat(sep=' '))
print("Custom:", dt.strftime("%Y-%m-%d %H:%M:%S"))

  1. dt ← 2025-01-29 14:30:45, d ← 2025-01-29, t ← 14:30:45, dt_utc ← 2025-01-15 10:30:00+00:00

    5# ISO 8601 formats6dt→ 2025-01-29 14:30:45 = datetime(2025, 1, 29, 14, 30, 45)7d→ 2025-01-29 = dt2025-01-29 14:30:45.date()8t→ 14:30:45 = dt2025-01-29 14:30:45.time()910# ISO date11print("ISO Date formats:")12print("isoformat():", d2025-01-29.isoformat())13print("ISO string:", str(d2025-01-29))1415# ISO time16print("\nISO Time formats:")17print("isoformat():", t14:30:45.isoformat())18print("ISO string:", str(t14:30:45))1920# ISO datetime21print("\nISO DateTime formats:")22print("isoformat():", dt2025-01-29 14:30:45.isoformat())23print("ISO with T:", dt2025-01-29 14:30:45.isoformat(sep='T'))24print("ISO with space:", dt2025-01-29 14:30:45.isoformat(sep=' '))2526# With timezone27dt_utc→ 2025-01-15 10:30:00+00:00 = datetime<class 'datetime.datetime'>.now(timezone.utcUTC).replace(28    year=2025, month=1, day=15, hour=10, minute=30, second=0, microsecond=029)30print("\nWith timezone:")31print("UTC datetime:", dt_utc2025-01-15 10:30:00+00:00.isoformat())3233# With microseconds34dt_micro→ 2025-01-29 14:30:45.123456 = datetime(2025, 1, 29, 14, 30, 45, 123456)35print("\nWith microseconds:")36print("Full precision:", dt_micro2025-01-29 14:30:45.123456.isoformat())37print("Truncated:", dt_micro2025-01-29 14:30:45.123456.isoformat(timespec='seconds'))3839# Different time specifications40print("\nTime specifications:")41for spec in ['auto', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds']:
    outputISO Date formats:
    isoformat(): 2025-01-29
    ISO string: 2025-01-29
    
    ISO Time formats:
    isoformat(): 14:30:45
    ISO string: 14:30:45
    
    ISO DateTime formats:
    isoformat(): 2025-01-29T14:30:45
    ISO with T: 2025-01-29T14:30:45
    ISO with space: 2025-01-29 14:30:45
    
    With timezone:
    UTC datetime: 2025-01-15T10:30:00+00:00
    
    With microseconds:
    Full precision: 2025-01-29T14:30:45.123456
    Truncated: 2025-01-29T14:30:45
    
    Time specifications:
  2. for spec in ['auto', 'hours', 'minutes', 'seconds', 'milliseconds', 'm…

    pass 1 of 6
    40print("\nTime specifications:")41for specauto in ['auto', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds']:42    print(f"{specauto:15}: {dt_micro2025-01-29 14:30:45.123456.isoformat(timespec=spec)}")
    outputauto           : 2025-01-29T14:30:45.123456
    All 6 passes — pass 1 is the card above
    passspec
    1auto
    2hours
    3minutes
    4seconds
    5milliseconds
    6microseconds
  3. iso_date ← 2025-01-29, parsed_date ← 2025-01-29, iso_time ← 14:30:45

    44# Parse ISO formats45print("\nParse ISO formats:")4647iso_date→ 2025-01-29 = "2025-01-29"48parsed_date→ 2025-01-29 = date<class 'datetime.date'>.fromisoformat(iso_date2025-01-29)49print(f"Date: {iso_date2025-01-29} -> {parsed_date2025-01-29}")5051iso_time→ 14:30:45 = "14:30:45"52parsed_time→ 14:30:45 = time<class 'datetime.time'>.fromisoformat(iso_time14:30:45)53print(f"Time: {iso_time14:30:45} -> {parsed_time14:30:45}")5455iso_datetime→ 2025-01-29T14:30:45 = "2025-01-29T14:30:45"56parsed_dt→ 2025-01-29 14:30:45 = datetime<class 'datetime.datetime'>.fromisoformat(iso_datetime2025-01-29T14:30:45)57print(f"DateTime: {iso_datetime2025-01-29T14:30:45} -> {parsed_dt2025-01-29 14:30:45}")5859# Compact formats60print("\nCompact formats:")61compact→ 20250129 = dt2025-01-29 14:30:45.strftime("%Y%m%d")62print("Date compact:", compact20250129)63compact_time→ 20250129T143045 = dt2025-01-29 14:30:45.strftime("%Y%m%dT%H%M%S")64print("DateTime compact:", compact_time20250129T143045)6566# ISO week date67print("\nISO week date:")68iso_calendar→ datetime.IsoCalendarDate(year=2025, week=5, weekday=3) = d2025-01-29.isocalendar()69print(f"Year: {iso_calendar.year2025}")70print(f"Week: {iso_calendar.week5}")71print(f"Weekday: {iso_calendar.weekday3}")72print(f"ISO week: {iso_calendar.year2025}-W{iso_calendar.week5:02d}-{iso_calendar.weekday3}")7374# Round-trip conversion75print("\nRound-trip:")76original→ 2025-01-15 10:30:00 = datetime<class 'datetime.datetime'>.now().replace(77    year=2025, month=1, day=15, hour=10, minute=30, second=0, microsecond=078)79iso_str→ 2025-01-15T10:30:00 = original2025-01-15 10:30:00.isoformat()80parsed→ 2025-01-15 10:30:00 = datetime<class 'datetime.datetime'>.fromisoformat(iso_str2025-01-15T10:30:00)81print(f"Original: {original2025-01-15 10:30:00}")82print(f"ISO string: {iso_str2025-01-15T10:30:00}")83print(f"Parsed: {parsed2025-01-15 10:30:00}")84print(f"Equal: {original2025-01-15 10:30:00 == parsed2025-01-15 10:30:00}")8586# Different separators87print("\nDifferent separators:")88print("T separator:", dt2025-01-29 14:30:45.isoformat(sep='T'))89print("Space separator:", dt2025-01-29 14:30:45.isoformat(sep=' '))90print("Custom:", dt2025-01-29 14:30:45.strftime("%Y-%m-%d %H:%M:%S"))
    output
    Parse ISO formats:
    Date: 2025-01-29 -> 2025-01-29
    Time: 14:30:45 -> 14:30:45
    DateTime: 2025-01-29T14:30:45 -> 2025-01-29 14:30:45
    
    Compact formats:
    Date compact: 20250129
    DateTime compact: 20250129T143045
    
    ISO week date:
    Year: 2025
    Week: 5
    Weekday: 3
    ISO week: 2025-W05-3
    
    Round-trip:
    Original: 2025-01-15 10:30:00
    ISO string: 2025-01-15T10:30:00
    Parsed: 2025-01-15 10:30:00
    Equal: True
    
    Different separators:
    T separator: 2025-01-29T14:30:45
    Space separator: 2025-01-29 14:30:45
    Custom: 2025-01-29 14:30:45
iso_format Working with ISO 8601 standard format for dates and times

Common Patterns

  • %Y-%m-%d: 2025-01-29
  • %H:%M:%S: 14:30:45
  • %Y-%m-%d %H:%M:%S: 2025-01-29 14:30:45

Format Codes

  • %Y: 4-digit year
  • %m: 2-digit month
  • %d: 2-digit day
  • %H: 24-hour (00-23)
  • %M: minute
  • %S: second

Locale-Aware Formatting

locale_format.py
Replay: real traced execution (multi-file project)
# Locale-specific formatting

from datetime import datetime
import locale

# Locale-specific formatting
dt = datetime(2025, 1, 29, 14, 30, 45)

print("DateTime:", dt)
print()

# Get current locale
print("Current locale:", locale.getlocale())
print()

# Default locale formatting
print("Default locale:")
print("%c (full):", dt.strftime("%c"))
print("%x (date):", dt.strftime("%x"))
print("%X (time):", dt.strftime("%X"))

# Different locale examples (may vary by system)
locales_to_try = [
    ('en_US.UTF-8', 'US English'),
    ('en_GB.UTF-8', 'UK English'),
    ('fr_FR.UTF-8', 'French'),
    ('de_DE.UTF-8', 'German')
]

print("\nLocale-specific formats:")
original_locale = locale.getlocale()

for loc, name in locales_to_try:
    try:
        locale.setlocale(locale.LC_TIME, loc)
        print(f"\n{name} ({loc}):")
        print("  Full:", dt.strftime("%c"))
        print("  Date:", dt.strftime("%x"))
        print("  Time:", dt.strftime("%X"))
        print("  Month:", dt.strftime("%B"))
        print("  Day:", dt.strftime("%A"))
    except locale.Error:
        print(f"\n{name}: locale not available")

# Restore original locale
try:
    locale.setlocale(locale.LC_TIME, original_locale)
except:
    locale.setlocale(locale.LC_TIME, '')

# Locale-aware format codes
print("\nLocale-aware codes:")
print("%c - Full datetime:", dt.strftime("%c"))
print("%x - Date:", dt.strftime("%x"))
print("%X - Time:", dt.strftime("%X"))
print("%B - Month name:", dt.strftime("%B"))
print("%b - Short month:", dt.strftime("%b"))
print("%A - Day name:", dt.strftime("%A"))
print("%a - Short day:", dt.strftime("%a"))
print("%p - AM/PM:", dt.strftime("%p"))

# Manual locale formatting
print("\nManual locale formatting:")

month_names = {
    'en': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    'es': ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
    'fr': ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc']
}

for lang, months in month_names.items():
    month_name = months[dt.month - 1]
    print(f"{lang}: {dt.day} {month_name} {dt.year}")

# Custom format function
def format_locale(dt, pattern, locale_name='en_US'):
    """Format datetime with specific locale"""
    original = locale.getlocale()
    try:
        locale.setlocale(locale.LC_TIME, locale_name)
        result = dt.strftime(pattern)
        locale.setlocale(locale.LC_TIME, original)
        return result
    except locale.Error:
        return dt.strftime(pattern)  # fallback

print("\nCustom locale function:")
patterns = ["%B", "%A", "%c"]
for pattern in patterns:
    formatted = format_locale(dt, pattern, 'en_US')
    print(f"{pattern}: {formatted}")

  1. dt ← 2025-01-29 14:30:45, locales_to_try ← [('en_US.UTF-8', 'US English'), ('en_GB.UTF-8', 'UK English'), ('fr_FR.UTF-8', 'French'), ('de_DE.UTF-8', 'German')]

    6# Locale-specific formatting7dt→ 2025-01-29 14:30:45 = datetime(2025, 1, 29, 14, 30, 45)89print("DateTime:", dt2025-01-29 14:30:45)10print()1112# Get current locale13print("Current locale:", locale<module 'locale' from '/usr/local/lib/python3.12/locale.py'>.getlocale())14print()1516# Default locale formatting17print("Default locale:")18print("%c (full):", dt2025-01-29 14:30:45.strftime("%c"))19print("%x (date):", dt2025-01-29 14:30:45.strftime("%x"))20print("%X (time):", dt2025-01-29 14:30:45.strftime("%X"))2122# Different locale examples (may vary by system)23locales_to_try→ [('en_US.UTF-8', 'US English'), ('en_GB.UTF-8', 'UK English'), ('fr_FR.UTF-8', 'French'), ('de_DE.UTF-8', 'German')] = [24    ('en_US.UTF-8', 'US English'),25    ('en_GB.UTF-8', 'UK English'),26    ('fr_FR.UTF-8', 'French'),27    ('de_DE.UTF-8', 'German')28]2930print("\nLocale-specific formats:")31original_locale→ ('C', 'UTF-8') = locale<module 'locale' from '/usr/local/lib/python3.12/locale.py'>.getlocale()
    outputDateTime: 2025-01-29 14:30:45
    Current locale: ('C', 'UTF-8')
    Default locale:
    %c (full): Wed Jan 29 14:30:45 2025
    %x (date): 01/29/25
    %X (time): 14:30:45
    
    Locale-specific formats:
  2. for loc, name in locales_to_try:

    pass 1 of 4
    33for locen_US.UTF-8, nameUS English in locales_to_try[('en_US.UTF-8', 'US English'), ('en_GB.UTF-8', 'UK English'), ('fr_FR.UTF-8', 'French'), ('de_DE.UTF-8', 'German')]:34    try:35        locale.setlocale(locale.LC_TIME, loc)
    All 4 passes — pass 1 is the card above
    passlocnamelocalelocale.LC_TIMEoriginal_locale
    1en_US.UTF-8US English
    2en_GB.UTF-8UK English
    3fr_FR.UTF-8French
    4de_DE.UTF-8German<module 'locale' from '/usr/local/lib/python3.12/locale.py'>2('C', 'UTF-8')
  3. try:

    pass 1 of 4
    33for loc, name in locales_to_try:34    try:35        locale<module 'locale' from '/usr/local/lib/python3.12/locale.py'>.setlocale(locale.LC_TIME2, locen_US.UTF-8)36        print(f"\n{name} ({loc}):")
    All 4 passes — pass 1 is the card above
    passlocoriginal_locale
    1en_US.UTF-8
    2en_GB.UTF-8
    3fr_FR.UTF-8
    4de_DE.UTF-8('C', 'UTF-8')
  4. except locale.Error:

    pass 1 of 4
    41    print("  Day:", dt.strftime("%A"))42except locale.Error:43    print(f"\n{nameUS English}: locale not available")
    output
    US English: locale not available
    
    US English: locale not available
    All 4 passes — pass 1 is the card above
    passnamelocalelocale.LC_TIMEoriginal_locale
    1US English
    2UK English
    3French
    4German<module 'locale' from '/usr/local/lib/python3.12/locale.py'>2('C', 'UTF-8')
  5. try:

    45# Restore original locale46try:47    locale<module 'locale' from '/usr/local/lib/python3.12/locale.py'>.setlocale(locale.LC_TIME2, original_locale('C', 'UTF-8'))48except:
  6. month_names ← {'en': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'es': ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'], 'fr': ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc']}

    51# Locale-aware format codes52print("\nLocale-aware codes:")53print("%c - Full datetime:", dt2025-01-29 14:30:45.strftime("%c"))54print("%x - Date:", dt2025-01-29 14:30:45.strftime("%x"))55print("%X - Time:", dt2025-01-29 14:30:45.strftime("%X"))56print("%B - Month name:", dt2025-01-29 14:30:45.strftime("%B"))57print("%b - Short month:", dt2025-01-29 14:30:45.strftime("%b"))58print("%A - Day name:", dt2025-01-29 14:30:45.strftime("%A"))59print("%a - Short day:", dt2025-01-29 14:30:45.strftime("%a"))60print("%p - AM/PM:", dt2025-01-29 14:30:45.strftime("%p"))6162# Manual locale formatting63print("\nManual locale formatting:")6465month_names→ {'en': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'es': ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'], 'fr': ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc']} = {66    'en': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],67    'es': ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],68    'fr': ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc']69}
    output
    Locale-aware codes:
    %c - Full datetime: Wed Jan 29 14:30:45 2025
    %x - Date: 01/29/25
    %X - Time: 14:30:45
    %B - Month name: January
    %b - Short month: Jan
    %A - Day name: Wednesday
    %a - Short day: Wed
    %p - AM/PM: PM
    
    Manual locale formatting:
  7. month_name ← Jan

    pass 1 of 3
    71for langen, months['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] in month_names{'en': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'es': ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'], 'fr': ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc']}.items():72    month_name→ Jan = months[dt.month - 1]Jan73    print(f"{langen}: {dt.day29} {month_nameJan} {dt.year2025}")
    outputen: 29 Jan 2025
    All 3 passes — pass 1 is the card above
    passlangmonthsmonths[dt.month - 1]month_name
    1en['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']JanJan
    2es['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic']EneEne
    3fr['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc']JanJan
  8. patterns ← ['%B', '%A', '%c']

    87print("\nCustom locale function:")88patterns→ ['%B', '%A', '%c'] = ["%B", "%A", "%c"]89for pattern in patterns:
    output
    Custom locale function:
  9. for pattern in patterns:

    pass 1 of 3
    88patterns = ["%B", "%A", "%c"]89for pattern%B in patterns['%B', '%A', '%c']:90    formatted = format_locale(dt2025-01-29 14:30:45, pattern%B, 'en_US')91    print(f"{pattern}: {formatted}")
    All 3 passes — pass 1 is the card above
    passpattern
    1%B
    2%A
    3%c
  10. original ← ('C', 'UTF-8')

    pass 1 of 3
    75# Custom format function76def format_locale(dt2025-01-29 14:30:45, pattern%B, locale_nameen_US='en_US'):77    """Format datetime with specific locale"""78    original→ ('C', 'UTF-8') = locale<module 'locale' from '/usr/local/lib/python3.12/locale.py'>.getlocale()79    try:
    All 3 passes — pass 1 is the card above
    passpatternoriginal
    1%B('C', 'UTF-8')
    2%A('C', 'UTF-8')
    3%c('C', 'UTF-8')
  11. try:

    pass 1 of 3
    78original = locale.getlocale()79try:80    locale<module 'locale' from '/usr/local/lib/python3.12/locale.py'>.setlocale(locale.LC_TIME2, locale_nameen_US)81    result = dt.strftime(pattern)
  12. except locale.Error:

    pass 1 of 3
    83    return result84except locale.Error:85    return dt2025-01-29 14:30:45.strftime(pattern%B)  # fallback
    All 3 passes — pass 1 is the card above
    passpattern
    1%B
    2%A
    3%c
  13. formatted ← January

    89for pattern in patterns:90    formatted→ January = format_locale(dt2025-01-29 14:30:45, pattern%B, 'en_US')91    print(f"{pattern%B}: {formattedJanuary}")
    output%B: January
  14. formatted ← Wednesday

    89for pattern in patterns:90    formatted→ Wednesday = format_locale(dt2025-01-29 14:30:45, pattern%A, 'en_US')91    print(f"{pattern%A}: {formattedWednesday}")
    output%A: Wednesday
  15. formatted ← Wed Jan 29 14:30:45 2025

    89for pattern in patterns:90    formatted→ Wed Jan 29 14:30:45 2025 = format_locale(dt2025-01-29 14:30:45, pattern%c, 'en_US')91    print(f"{pattern%c}: {formattedWed Jan 29 14:30:45 2025}")
    output%c: Wed Jan 29 14:30:45 2025
locale_format Formatting dates according to regional conventions

Exercise: practical.py

Create log formatters, filename generators, and user-friendly date displays