]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Pad second fractions to micros using a lookup table
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 7 Jun 2021 20:44:00 +0000 (21:44 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 7 Jun 2021 21:17:51 +0000 (22:17 +0100)
psycopg3/psycopg3/types/date.py
psycopg3_c/psycopg3_c/types/date.pyx

index 9f71a9181caa753ac69bb8675ddd65c05fb7e3c5..5c217720672b9c09c7ca053d9e19a4a76f75f134 100644 (file)
@@ -324,10 +324,9 @@ class TimeLoader(Loader):
 
         # Pad the fraction of second to get millis
         if ms:
-            if len(ms) == 6:
-                ims = int(ms)
-            else:
-                ims = int(ms + _ms_trail[len(ms)])
+            ims = int(ms)
+            if len(ms) < 6:
+                ims *= _uspad[len(ms)]
         else:
             ims = 0
 
@@ -379,10 +378,9 @@ class TimetzLoader(Loader):
 
         # Pad the fraction of second to get millis
         if ms:
-            if len(ms) == 6:
-                ims = int(ms)
-            else:
-                ims = int(ms + _ms_trail[len(ms)])
+            ims = int(ms)
+            if len(ms) < 6:
+                ims *= _uspad[len(ms)]
         else:
             ims = 0
 
@@ -517,10 +515,9 @@ class TimestampLoader(Loader):
 
         # Pad the fraction of second to get millis
         if ms:
-            if len(ms) == 6:
-                ims = int(ms)
-            else:
-                ims = int(ms + _ms_trail[len(ms)])
+            ims = int(ms)
+            if len(ms) < 6:
+                ims *= _uspad[len(ms)]
         else:
             ims = 0
 
@@ -589,10 +586,9 @@ class TimestamptzLoader(Loader):
 
         # Pad the fraction of second to get millis
         if ms:
-            if len(ms) == 6:
-                ims = int(ms)
-            else:
-                ims = int(ms + _ms_trail[len(ms)])
+            ims = int(ms)
+            if len(ms) < 6:
+                ims *= _uspad[len(ms)]
         else:
             ims = 0
 
@@ -746,4 +742,4 @@ _month_abbr = {
 }
 
 # Pad to get milliseconds from a fraction of seconds
-_ms_trail = [b"000000", b"00000", b"0000", b"000", b"00", b"0"]
+_uspad = [0, 100_000, 10_000, 1_000, 100, 10, 1]
index 9fcb306578864c1ae2adf5acfdefca8fa2664548..b8af95bbff9f06a259b23d06d0ad85f69cabf3bb 100644 (file)
@@ -14,13 +14,17 @@ cdef extern from "Python.h":
     const char *PyUnicode_AsUTF8AndSize(unicode obj, Py_ssize_t *size) except NULL
     object PyTimeZone_FromOffset(object offset)
 
-# Hack to compile on Python 3.6
 cdef extern from *:
     """
+/* Hack to compile on Python 3.6 */
 #if PY_VERSION_HEX < 0x03070000
 #define PyTimeZone_FromOffset(x) x
 #endif
+
+/* Multipliers from fraction of seconds to microseconds */
+static int _uspad[] = {0, 100000, 10000, 1000, 100, 10, 1};
     """
+    cdef int *_uspad
 
 from datetime import date, time, timedelta, datetime, timezone
 
@@ -876,7 +880,7 @@ cdef const char *_parse_date_values(const char *ptr, int *vals, int nvals):
     return ptr
 
 
-cdef const char *_parse_micros(const char *ptr, int *us):
+cdef const char *_parse_micros(const char *start, int *us):
     """
     Parse microseconds from a string.
 
@@ -884,21 +888,18 @@ cdef const char *_parse_micros(const char *ptr, int *us):
 
     Return the pointer at the separator after the final digit.
     """
-    cdef int ndigits = 0
+    cdef const char *ptr = start
     while ptr[0]:
         if b'0' <= ptr[0] <= b'9':
             us[0] = us[0] * 10 + (ptr[0] - <char>b'0')
-            ndigits += 1
         else:
             break
 
         ptr += 1
 
     # Pad the fraction of second to get millis
-    if us[0]:
-        while ndigits < 6:
-            us[0] *= 10
-            ndigits += 1
+    if us[0] and ptr - start < 6:
+        us[0] *= _uspad[ptr - start]
 
     return ptr