I am building an application using Python 3.13.5 and the native sqlite3 library. To correctly handle datetime.date objects and avoid the new DeprecationWarning, I am trying to implement the officially recommended custom adapter and converter pattern.
Despite registering a custom adapter for the datetime.date type, the DeprecationWarning: The default date adapter is deprecated... is still being triggered every time I execute an INSERT statement with a date object.
Interestingly, my custom converter (for reading DATE columns from the DB) seems to work correctly when I use the detect_types=sqlite3.PARSE_DECLTYPES flag. The problem seems to be exclusively with the adapter (for writing Python date objects to the DB), which appears to be ignored, causing sqlite3 to fall back to its deprecated default method.
I have isolated the problem in the following minimal, self-contained script. This script does not use pytest or any external libraries.
import sqlite3
from datetime import datetime, date
import sys
###############################################################################
print('\n')
print(f'=' * 25, '--- PYTHON AND SQLITE3 VERSION ---', '=' * 25)
print(f'Python Version: {sys.version}')
print(f'Sqlite3 Version: {sqlite3.sqlite_version_info}')
print(f'=' * 50)
###############################################################################
#################### --- ADAPTERS AND CONVERSORS --- ####################
def date_adapter(object_date: date) -> str:
'receives an object_date in the date adapter for adaptation to the new pattern of sqlite3'
adapter_format_str = object_date.isoformat()
return adapter_format_str
def date_conversor(object_bytes: bytes) -> date:
'receives an object_bytes from database for the converting in a object_date to python'
convert_object_str = object_bytes.decode()
adapter_format_date = datetime.strptime(convert_object_str, '%Y-%m-%d').date()
return adapter_format_date
####### --- DATE OBJECT -> BYTES (STR) OBJECT --- #######
sqlite3.register_adapter(datetime.date, date_adapter)
####### --- BYTES (STR) OBJECT -> DATE OBJECT --- #######
sqlite3.register_converter('date', date_conversor)
####### --- CREATING AN DB WITHIN MEMORY --- #######
test_conn = sqlite3.connect(':memory:', detect_types = sqlite3.PARSE_DECLTYPES)
cursor = test_conn.cursor()
object_today = date.today()
###############################################################################
print(f'=' * 25, '--- TYPE INPUT ---', '=' * 25)
print(f'[DEBUG] Type Object Input in Database: {type(object_today)}')
print(f'=' * 50)
print('\n')
print(f'#' * 25, '--- WARNING HERE ---', '#' * 25)
###############################################################################
####### --- CREATING TABLE, INSERTING VALUE AND SELECTING THE OBJECT--- #######
cursor.execute('''
CREATE TABLE IF NOT EXISTS test (
id INTEGER PRYMARY KEY,
date_today DATE NOT NULL
)
''')
cursor.execute('''
INSERT INTO test (date_today)
VALUES (?)
''',
(
object_today,
))
cursor.execute('''
SELECT *
FROM test
''')
return_database = cursor.fetchall()
test_conn.commit()
test_conn.close()
###############################################################################
print(f'#' * 25, '--- WARNING HERE ---', '#' * 25)
print('\n')
print(f'=' * 25, '--- TYPE OUTPUT ---', '=' * 25)
print(f'[DEBUG] Type Object Output from Database: {type(return_database[0][1])}')
print(f'=' * 50)
###############################################################################
When I run this script, I get the following output:
========================= --- PYTHON AND SQLITE3 VERSION --- =========================
Python Version: 3.13.5 (tags/v3.13.5:6cb20a2, Jun 11 2025, 16:15:46) [MSC v.1943 64 bit (AMD64)]
Sqlite3 Version: (3, 49, 1)
==================================================
========================= --- TYPE INPUT --- =========================
[DEBUG] Type Object Input in Database: <class 'datetime.date'>
==================================================
######################### --- WARNING HERE --- #########################
c:\Users\Lider CPD\Desktop\Joao - Arquivos\Particularidades - Joao\Projetos Python\gestaofarma_simples\debug_data.py:50: DeprecationWarning: The default date adapter is deprecated as of Python 3.12; see the sqlite3 documentation for suggested replacement recipes
cursor.execute('''
######################### --- WARNING HERE --- #########################
========================= --- TYPE OUTPUT --- =========================
[DEBUG] Type Object Output from Database: <class 'datetime.date'>
==================================================
What I've Tried I have confirmed the column type in CREATE TABLE is DATE.
My adapter function (date_adapter) is correct and returns a string as required.
I have confirmed the problem exists both within my pytest test suite and in the minimal script above, so it is not a pytest-specific issue.
The registration is happening before any connection is made.
My Question What am I missing in the registration or connection setup that is causing sqlite3 to ignore my custom registered adapter for datetime.date and fall back to the deprecated default? Is there a known issue or a change in behavior in Python 3.13.5 that is not explicitly covered in the main documentation "recipes"?
--- EDIT: Solution --- User LMC's answer below resolved the issue.
There's a subtle minor issue with date types.
The import creates a datetime and a date objects but the registration uses datetime.date
sqlite3.register_adapter(datetime.date, date_adapter)
Using just date makes the warning go away and the adapter is called
sqlite3.register_adapter(date, date_adapter)
Add a print statement to verify
def date_adapter(object_date: date) -> str:
'receives an object_date in the date adapter for adaptation to the new pattern of sqlite3'
print('Adapter called')
adapter_format_str = object_date.isoformat()
return adapter_format_str
Stdout:
========================= --- PYTHON AND SQLITE3 VERSION --- =========================
Python Version: 3.12.11 (main, Jun 10 2025, 09:17:07) [GCC]
Sqlite3 Version: (3, 50, 2)
==================================================
========================= --- TYPE INPUT --- =========================
[DEBUG] Type Object Input in Database: <class 'datetime.date'>
==================================================
######################### --- WARNING HERE --- #########################
Adapter called
######################### --- WARNING HERE --- #########################
========================= --- TYPE OUTPUT --- =========================
[DEBUG] Type Object Output from Database: <class 'str'>
==================================================
As @j-earls pointed out in a comment datetime.date is a method
>>> from datetime import datetime, date
>>> datetime.date
<method 'date' of 'datetime.datetime' objects>
>>> date
<class 'datetime.date'>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With