This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author bozo.kopic
Recipients bozo.kopic
Date 2016-12-28.23:04:29
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1482966269.67.0.620298847284.issue29099@psf.upfronthosting.co.za>
In-reply-to
Content
Current convert_timestamp function raises exception when parsing timestamps that contain timezone information and have microsecond set to zero.

Patch for this behavior is included.

Example script that demonstrates this problem:

import sys
import datetime
import sqlite3
import traceback
import contextlib


def main():
    db = sqlite3.connect('test.db', detect_types=sqlite3.PARSE_DECLTYPES)
    db.executescript("""
        CREATE TABLE IF NOT EXISTS test (
            timestamp TIMESTAMP)
        """)

    t = datetime.datetime.now(tz=datetime.timezone.utc)
    t = t.replace(microsecond=0)
    db.executemany("INSERT INTO test VALUES (:timestamp)", [{'timestamp': t}])
    db.commit()

    with contextlib.closing(db.cursor()) as c:
        try:
            c.execute('SELECT * FROM test')
            c.fetchall()
            print('original implementation success')
        except Exception as e:
            print('original implementation failed')
            traceback.print_exc()
        c.close()

    sqlite3.register_converter("timestamp", _sqlite_convert_timestamp)

    with contextlib.closing(db.cursor()) as c:
        try:
            c.execute('SELECT * FROM test')
            c.fetchall()
            print('patched implementation success')
        except Exception as e:
            print('patched implementation failed')
            traceback.print_exc()
        c.close()


def _sqlite_convert_timestamp(val):
    datepart, timepart = val.split(b" ")

    # this is the patch
    timepart = timepart.split(b'+', 1)[0].split(b'-', 1)[0]

    year, month, day = map(int, datepart.split(b"-"))
    timepart_full = timepart.split(b".")
    hours, minutes, seconds = map(int, timepart_full[0].split(b":"))
    if len(timepart_full) == 2:
        microseconds = int('{:0<6.6}'.format(timepart_full[1].decode()))
    else:
        microseconds = 0
    val = datetime.datetime(year, month, day, hours, minutes, seconds,
                            microseconds)
    return val


if __name__ == '__main__':
    sys.exit(main())
History
Date User Action Args
2016-12-28 23:04:29bozo.kopicsetrecipients: + bozo.kopic
2016-12-28 23:04:29bozo.kopicsetmessageid: <1482966269.67.0.620298847284.issue29099@psf.upfronthosting.co.za>
2016-12-28 23:04:29bozo.kopiclinkissue29099 messages
2016-12-28 23:04:29bozo.kopiccreate