Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mysqldb converts timestamp data to None

I am using MySQLdb to talk to mysql database and I am able to retrieve dynamically all the result sets.

My problem is that once I get the result set, there are a couple columns which are declared as timestamps in mysql but when it is retrieved, it turns to None.

I have two columns, both are declared timestamps but one returns correct data while other returns None. Both utime and enddate are declared timestamps but utime does not return correctly while enddate does.

['utime', 'userstr', 'vstr_client', 'enddate']

((None, '000102030ff43260gg0809000000000004', '7.7.0', '1970-01-01 12:00:00.000000'))

def parse_data_and_description(cursor, data):

    res = []
    cols = [d[0] for d in cursor.description]
    print cols
    print data

    for i in data:
        res.append(OrderedDict(zip(cols, i)))
    return res

def call_multi_rs(sp, args):

    rs_id=0;
    conn = connect()
    cursor = conn.cursor()
    try:
        conn.autocommit(True)
        cursor.execute ("CALL %s%s" % (sp, args))
        while True:
            rs_id+=1
            data = cursor.fetchone( )
            listout = parse_data_and_description(cursor, data)
            print listout
            if cursor.nextset( )==None:
            # This means no more recordsets available
            break
like image 311
ronak Avatar asked Mar 14 '13 21:03

ronak


People also ask

Is it better to use TIMESTAMP or datetime?

Timestamps are also lighter on the database and indexed faster. The DATETIME type is used when you need values that contain both date and time information. MySQL retrieves and displays DATETIME values in YYYY-MM-DD HH:MM:SS format.

Does MySQL support TIMESTAMP?

MySQL retrieves and displays DATETIME values in ' YYYY-MM-DD hh:mm:ss ' format. The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59' . The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.

Is TIMESTAMP same as datetime?

Just as DATETIME , the TIMESTAMP data type contains both the date and the time in the following format YYYY-MM-DD hh:mm:ss . However, unlike DATETIME , the TIMESTAMP data type has a fixed range between 1970-01-01 00:00:01 UTC to 2038-01-19 03:14:07 UTC.

How is TIMESTAMP stored in MySQL?

Timestamp supports Universal Time Coordinated(UTC) for MySQL. The Timestamp is written in a format that is set at 19 characters: YYYY-MM-DD HH:MM: SS. The values for Timestamp data type ranges from date 1st January 1970 UTC to 19th January 2038 UTC.


2 Answers

Finally after nobody answered or tried finding more information, I went ahead and looked for more solutions and found that the MySQLdb library converts the datatypes from sql to python and there is a bug which does not convert the timestamp.

I still do not know why one of them is converted and the other is not. If somebody can figure that out, please update this.

But here is the modification that needs to be done when connecting to the mysql database. MySQLdb can't serialize a python datetime object

try:
    import MySQLdb.converters
except ImportError:
    _connarg('conv')

def connect(host='abc.dev.local', user='abc', passwd='def', db='myabc', port=3306):

    try:
        orig_conv = MySQLdb.converters.conversions
        conv_iter = iter(orig_conv)
        convert = dict(zip(conv_iter, [str,] * len(orig_conv.keys())))
        print "Connecting host=%s user=%s db=%s port=%d" % (host, user, db, port)
        conn = MySQLdb.connect(host, user, passwd, db, port, conv=convert)
    except MySQLdb.Error, e:
        print "Error connecting %d: %s" % (e.args[0], e.args[1])
    return conn
like image 134
ronak Avatar answered Sep 28 '22 16:09

ronak


I stumbled upon the same problem: Retrieving data of the DATETIME(1)-type returns None.

Some research brought up MySQLdb-Bug #325. According to that bug tracker, the issue is still open (has been for over 2 years now), but the comments provide a working solution:

In times.py of the MySQLdb package, you need to insert some lines to handle microseconds like this:

def DateTime_or_None(s):
    if ' ' in s:
       sep = ' '
    elif 'T' in s:
        sep = 'T'
    else:
        return Date_or_None(s)

    try:
        d, t = s.split(sep, 1)
        if '.' in t:
            t, ms = t.split('.',1)
            ms = ms.ljust(6, '0')
        else:
            ms = 0
        return datetime(*[ int(x) for x in d.split('-')+t.split(':')+[ms] ])
    except (SystemExit, KeyboardInterrupt):
        raise
    except:
        return Date_or_None(s)

def TimeDelta_or_None(s):
    try:
        h, m, s = s.split(':')
        if '.' in s:
            s, ms = s.split('.')
            ms = ms.ljust(6, '0')
        else:
            ms = 0
        h, m, s, ms = int(h), int(m), int(s), int(ms)
        td = timedelta(hours=abs(h), minutes=m, seconds=s,
                       microseconds=ms)
        if h < 0:
            return -td
        else:
            return td
    except ValueError:
        # unpacking or int/float conversion failed
        return None

def Time_or_None(s):
    try:
        h, m, s = s.split(':')
        if '.' in s:
            s, ms = s.split('.')
            ms = ms.ljust(6, '0')
        else:
            ms = 0
        h, m, s, ms = int(h), int(m), int(s), int(ms)
        return time(hour=h, minute=m, second=s, microsecond=ms)
    except ValueError:
        return None

What I cannot explain, though, is your original query working on one column and not on the other.. Maybe, the second does not have any microsecond-information in it?

like image 30
Fantilein1990 Avatar answered Sep 28 '22 15:09

Fantilein1990