From df50e23f28dc7f8347e458318a2a91b044880157 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 15 May 2021 13:23:26 +0200 Subject: [PATCH] Base time loader on regexp Some 5x faster --- psycopg3/psycopg3/types/date.py | 35 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/psycopg3/psycopg3/types/date.py b/psycopg3/psycopg3/types/date.py index d9e7c737f..2f3f2d656 100644 --- a/psycopg3/psycopg3/types/date.py +++ b/psycopg3/psycopg3/types/date.py @@ -323,28 +323,27 @@ class DateBinaryLoader(Loader): class TimeLoader(Loader): format = Format.TEXT - _format = "%H:%M:%S.%f" - _format_no_micro = _format.replace(".%f", "") + + _re_format = re.compile(rb"^(\d+):(\d+):(\d+)(?:\.(\d+))?") def load(self, data: Buffer) -> time: - # check if the data contains microseconds - if isinstance(data, memoryview): - data = bytes(data) - fmt = self._format if b"." in data else self._format_no_micro - try: - return datetime.strptime(data.decode("utf8"), fmt).time() - except ValueError as e: - return self._raise_error(data, e) + m = self._re_format.match(data) + if not m: + s = bytes(data).decode("utf8", "replace") + raise DataError(f"can't parse time {s!r}") - def _raise_error(self, data: bytes, exc: ValueError) -> time: - # Most likely, time 24:00 - if data.startswith(b"24"): - raise DataError( - f"time not supported by Python: {data.decode('ascii')}" - ) + ho, mi, se, ms = m.groups() + + if ms is None: + ms = b"0" + elif len(ms) < 6: + ms += b"0" * (6 - len(ms)) - # We genuinely received something we cannot parse - raise exc + try: + return time(int(ho), int(mi), int(se), int(ms)) + except ValueError as e: + s = bytes(data).decode("utf8", "replace") + raise DataError(f"can't manage time {s!r}: {e}") class TimeBinaryLoader(Loader): -- 2.47.3