From 8ab27f26b90bbb12898ecb10ff08e7225898b5e9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 12 May 2022 20:11:43 -0400 Subject: [PATCH] Use ciso8601 for parsing datetimes with sqlalchemy sqlite dialect (#71766) --- homeassistant/components/recorder/models.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/recorder/models.py b/homeassistant/components/recorder/models.py index 38d6b3319aa..6edee252ea3 100644 --- a/homeassistant/components/recorder/models.py +++ b/homeassistant/components/recorder/models.py @@ -6,6 +6,7 @@ import json import logging from typing import Any, TypedDict, cast, overload +import ciso8601 from fnvhash import fnv1a_32 from sqlalchemy import ( BigInteger, @@ -22,7 +23,7 @@ from sqlalchemy import ( Text, distinct, ) -from sqlalchemy.dialects import mysql, oracle, postgresql +from sqlalchemy.dialects import mysql, oracle, postgresql, sqlite from sqlalchemy.engine.row import Row from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.orm import declarative_base, relationship @@ -91,8 +92,18 @@ TABLES_TO_CHECK = [ EMPTY_JSON_OBJECT = "{}" -DATETIME_TYPE = DateTime(timezone=True).with_variant( - mysql.DATETIME(timezone=True, fsp=6), "mysql" +class FAST_PYSQLITE_DATETIME(sqlite.DATETIME): # type: ignore[misc] + """Use ciso8601 to parse datetimes instead of sqlalchemy built-in regex.""" + + def result_processor(self, dialect, coltype): # type: ignore[no-untyped-def] + """Offload the datetime parsing to ciso8601.""" + return lambda value: None if value is None else ciso8601.parse_datetime(value) + + +DATETIME_TYPE = ( + DateTime(timezone=True) + .with_variant(mysql.DATETIME(timezone=True, fsp=6), "mysql") + .with_variant(FAST_PYSQLITE_DATETIME(), "sqlite") ) DOUBLE_TYPE = ( Float()