Skip to main content

How to Resolve Python Error "TypeError: descriptor 'date' for 'datetime.datetime' objects doesn't apply to a 'int' object"

The TypeError: descriptor 'date' for 'datetime.datetime' objects doesn't apply to a 'int' object can be a confusing error when working with Python's datetime module. It typically arises from a misunderstanding of how the date class relates to the datetime class within the datetime module, leading to an incorrect attempt to create a date object.

This guide clarifies the structure of the datetime module and provides the correct ways to create date objects, resolving this specific TypeError.

Understanding the Error: Module vs. Classes (datetime, date, time)

It's crucial to distinguish between:

  • datetime (lowercase): The module you import (import datetime). It acts as a container for related classes and functions.
  • datetime.date (Module.Class): The class inside the datetime module used to represent a date (year, month, day).
  • datetime.datetime (Module.Class): The class inside the datetime module used to represent a specific point in time (date and time components).

The error message, while mentioning int objects (because you're likely passing integer arguments like year, month, day), fundamentally arises because you're trying to use the date component/descriptor of the datetime.datetime class as if it were the constructor for the date class itself.

import datetime

# Showing the types clearly:
print(f"Type of 'datetime' module: {type(datetime)}")
# Output: Type of 'datetime' module: <class 'module'>

print(f"Type of 'datetime.date' class: {type(datetime.date)}")
# Output: Type of 'datetime.date' class: <class 'type'> (Note: it's a class)

print(f"Type of 'datetime.datetime' class: {type(datetime.datetime)}")
# Output: Type of 'datetime.datetime' class: <class 'type'> (Note: it's a class)

Output:

Type of 'datetime' module: <class 'module'>
Type of 'datetime.date' class: <class 'type'>
Type of 'datetime.datetime' class: <class 'type'>

The Cause: Incorrectly Accessing date via datetime.datetime

The TypeError occurs when you incorrectly try to instantiate a date object by going through the datetime.datetime class like this: datetime.datetime.date(...).

import datetime

year = 2024
month = 3
day = 15

try:
# ⛔️ TypeError: descriptor 'date' for 'datetime.datetime' objects doesn't apply to a 'int' object
# This attempts to call the 'date' descriptor/attribute of the 'datetime' class,
# not the 'date' class constructor itself.
d = datetime.datetime.date(year, month, day)
print(d)
except TypeError as e:
print(e)

Python interprets datetime.datetime.date as trying to call an attribute named date that belongs to the datetime.datetime class (which is normally used like my_datetime_object.date() to get the date part from a datetime object), not as the constructor for creating a new date object.

Solution 1: Access date Directly from the datetime Module

The date class is directly available as an attribute of the top-level datetime module. Access it as datetime.date().

import datetime # Import the module

year = 2025
month = 3
day = 15

# ✅ Correct: Call the 'date' class constructor via the 'datetime' module
d = datetime.date(year, month, day)

print(f"Created date object: {d}") # Output: Created date object: 2025-03-15
print(f"Type of object: {type(d)}") # Output: Type of object: <class 'datetime.date'>

Output:

Created date object: 2025-03-15
Type of object: <class 'datetime.date'>

The datetime.date() constructor requires three integer arguments: year, month, and day within valid ranges (1 <= month <= 12, 1 <= day <= number of days in month). Providing invalid arguments raises a ValueError.

For better readability and less potential confusion (especially avoiding datetime.datetime), import the date class directly from the module.

# ✅ Import the 'date' class specifically
from datetime import date

year = 2025
month = 3
day = 15

# ✅ Correct: Call the imported 'date' class constructor directly
d = date(year, month, day)

print(f"Created date object: {d}") # Output: Created date object: 2025-03-15
print(f"Type of object: {type(d)}") # Output: Type of object: <class 'datetime.date'>

Output:

Created date object: 2025-03-15
Type of object: <class 'datetime.date'>

This approach makes it clearer that you are working with the date class and avoids the somewhat confusing datetime.datetime syntax.

When to Use datetime.datetime vs. datetime.date

  • Use datetime.date() (or date() after import) when you only need to represent a date (year, month, day) without any time information.
  • Use datetime.datetime() (or datetime() after from datetime import datetime) when you need to represent a specific point in time, including hours, minutes, seconds, etc., in addition to the date.
from datetime import date, datetime

just_a_date = date(2025, 3, 15)
date_and_time = datetime(2025, 3, 15, 10, 30, 0) # Year, Month, Day, Hour, Minute, Second

print(f"Date object: {just_a_date}") # Output: Date object: 2025-03-15
print(f"Datetime object: {date_and_time}") # Output: Datetime object: 2025-03-15 10:30:00

Output:

Date object: 2025-03-15
Datetime object: 2025-03-15 10:30:00

Debugging with type() and dir()

If unsure about what you have imported or created:

  • print(type(variable)) shows the type of an object.
  • print(dir(module)) shows attributes available directly within the module (like date and datetime).
  • print(dir(Class)) shows attributes available on the class (like class methods now, strptime).
import datetime
from datetime import date as date_class_alias # Alias to avoid confusion below

print("--- dir(datetime module) ---")
print(dir(datetime)) # Shows 'date', 'datetime', 'time', 'timedelta' etc.
print()

print("--- dir(datetime.date class) ---")
print(dir(datetime.date)) # Shows methods like 'today', 'fromisoformat', 'weekday' etc.
print()

print("--- dir(datetime.datetime class) ---")
print(dir(datetime.datetime)) # Shows methods like 'now', 'strptime', 'date', 'time' etc.
print()

# Using the imported alias
print("--- dir(date_class_alias) ---")
print(dir(date_class_alias)) # Same as dir(datetime.date)

Output:

--- dir(datetime module) ---
['MAXYEAR', 'MINYEAR', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'date', 'datetime', 'datetime_CAPI', 'sys', 'time', 'timedelta', 'timezone', 'tzinfo']

--- dir(datetime.date class) ---
['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'ctime', 'day', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'min', 'month', 'replace', 'resolution', 'strftime', 'timetuple', 'today', 'toordinal', 'weekday', 'year']

--- dir(datetime.datetime class) ---
['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'astimezone', 'combine', 'ctime', 'date', 'day', 'dst', 'fold', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'hour', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'microsecond', 'min', 'minute', 'month', 'now', 'replace', 'resolution', 'second', 'strftime', 'strptime', 'time', 'timestamp', 'timetuple', 'timetz', 'today', 'toordinal', 'tzinfo', 'tzname', 'utcfromtimestamp', 'utcnow', 'utcoffset', 'utctimetuple', 'weekday', 'year']

--- dir(date_class_alias) ---
['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'ctime', 'day', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'min', 'month', 'replace', 'resolution', 'strftime', 'timetuple', 'today', 'toordinal', 'weekday', 'year']

Pitfall: Variable Shadowing

If you use from datetime import date, avoid naming one of your own variables date, as this will overwrite the imported class name in that scope.

from datetime import date

my_year = 2024
# ⚠️ Problematic: Variable named 'date' shadows the imported class
date = (my_year, 3, 15) # This is now a tuple, not the date class

try:
# ⛔️ TypeError: 'tuple' object is not callable
d = date(my_year, 3, 15) # Trying to call the tuple variable
except TypeError as e:
print(e)

Solution: Use distinct variable names (e.g., current_date, d, date_obj).

from datetime import date

my_year = 2025
current_date = (my_year, 3, 15) # This is now a tuple, not the date class
d = date(my_year, 3, 15) # Trying to call the tuple variable
print(d) # Output: 2025-03-15

Conclusion

The TypeError: descriptor 'date' for 'datetime.datetime' objects doesn't apply to a 'int' object arises from incorrectly trying to create a date object via datetime.datetime.date(...).

The correct ways to create a date object are:

  1. Import the module and use the full path: import datetime; my_date = datetime.date(y, m, d)
  2. (Recommended) Import the class directly: from datetime import date; my_date = date(y, m, d)

Understanding the distinction between the datetime module and the date and datetime classes within it is key to using the module correctly and avoiding this error.