2016-04-18 14 views
7

Sto leggendo in vari tipi di dati da un database mySQL. La quinta colonna ha tipo 'DATETIME' nel database. Lo uso come entry_date per un oggetto 'BloodTraitRecord'.Come posso impedire a python di convertire un mySQL DATETIME in un datetime.date quando l'ora è 00:00:00?

classe
import mysql.connector 
from datetime import timedelta 
from datetime import datetime 

show_DB = """select RUID, test_sname, test_value, units, ref_range, entry_date from %s 
      where RUID=%%s and test_sname=%%s order by RUID, 
      test_sname, entry_date Limit 5;""" % (tableToUse,) 

cursor.execute(show_DB, (ruid, traitPair[0])) 
resultsForOneTrait = cursor.fetchall() 

for result in resultsForOneTrait: 
    ruid = result[0] 
    s_name = result[1].decode("UTF-8") 
    value = result[2] 
    units = result[3].decode("UTF-8") 
    ref_range = result[4].decode("UTF-8") 

    # Need assistance here 
    entryDate = result[5] 

    record = BloodTraitRecord(ruid, s_name, value, units, ref_range, entryDate) 

BloodTraitRecord:

class BloodTraitRecord: 

def __init__(self, ruid, test_sname, test_value, units, ref_range, entry_date): 
    self.RUID = ruid 
    self.test_sname = test_sname  
    self.test_value = test_value 
    self.units = units    
    self.ref_range = ref_range 


    self.entry_date = entry_date 

oggetti DateTime dal database simile a questa nel server MySQL:

'2008-11-14 13:28:00' 

Le funzioni di codice come previsto a meno che il tempo nel database è di mezzanotte , così:

'2014-05-18 00:00:00' 

In questo caso, e solo quel caso, ottengo questo errore quando si confrontano entry_date.date del record() ad un altro datetime.date più avanti nel codice:

# 'cancerCutoff' is consistently a datetime.date 
cancerCutoff = firstCancerAnemiaCodeDate[ruidkey] - timedelta(days=180) 
if cancerCutoff < record.entry_date.date(): 
AttributeError: 'datetime.date' object has no attribute 'date' 

stampa record.entry_date conferma che l'attributo di tempo è andato per questo caso:

'2014-05-18' 

ho un modo per risolvere questo controllando il tipo di oggetto, e solo chiamando l'attributo data, se l'oggetto è un datetime, ma mi chiedo se c'è un soluzione migliore di questa.

Inoltre non capisco perché python converta immediatamente il DATETIME MySQL in un datetime.date quando il tempo DATETIME è 00:00:00.

Grazie per il vostro aiuto!

+1

Stai dicendo che Python converte il DATETIME di MySQL in un 'datetime.date' se il valore include mezzanotte, ma non altrimenti? Quale ORM o connettore stai usando? Sembra 'mysql.connector', ma per favore conferma nella domanda. – ChrisP

+0

Tutto ciò è corretto. Aggiornamento della domanda. – Dylan

+0

I * non può * replicare il problema con 'mysql.connector' versione 2.1.3 e Python 3.5 in esecuzione su OSX con un server MySQL 5.6.24 locale. Che versioni stai correndo? – ChrisP

risposta

1

Accertarsi di disporre di un oggetto datetime non appena lo si estrae dal database. Quindi non devi fare alcun controllo in futuro. Quindi si può dire:

entryDate = ensure_datetime(result[5]) 

che è solo un po 'di codice in più e ha anche il vantaggio che se le modifiche di query e non si aggiorna correttamente il codice dopo che ti cattura immediatamente errori di tipo. Ecco un esempio di implementazione:

from datetime import datetime, date 

# Thanks to http://stackoverflow.com/a/1937636/2482744 
def date_to_datetime(d): 
    return datetime.combine(d, datetime.min.time()) 

def ensure_datetime(d): 
    if isinstance(d, datetime): 
     return d 
    elif isinstance(d, date): 
     return date_to_datetime(d) 
    else: 
     raise TypeError('%s is neither a date nor a datetime' % d) 

Demo:

for x in [date(2016, 5, 12), 
      datetime(2016, 5, 12, 9, 32, 57, 345), 
      'a string']: 
    print(ensure_datetime(x)) 

uscita:

2016-05-12 00:00:00 
2016-05-12 09:32:57.000345 
Traceback (most recent call last): 
    File "/Users/alexhall/Dropbox/python/sandbox/sandbox.py", line 14, in <module> 
    print(ensure_datetime(x)) 
    File "/Users/alexhall/Dropbox/python/sandbox/sandbox.py", line 9, in ensure_datetime 
    raise TypeError('%s is neither a date nor a datetime' % d) 
TypeError: a string is neither a date nor a datetime 

Ma ho la sensazione che non vuole avere a che fare questo, quindi mi addolcire come segue:

def clean_types(row): 
    new_row = [] 
    for item in row: 
     if isinstance(item, date) and not isinstance(item, datetime): 
      item = date_to_datetime(item) 
     elif isinstance(item, str): 
      item = item.decode("UTF-8") 
     new_row.append(item) 
    return new_row 

# Demo 
print(clean_types([3, 'abc', u'def', date.today(), datetime.now()])) 
# [3, u'abc', u'def', datetime.datetime(2016, 5, 12, 0, 0), datetime.datetime(2016, 5, 12, 17, 22, 7, 519604)] 

Ora la tua c l'ode può essere abbreviato a:

for result in resultsForOneTrait: 
    record = BloodTraitRecord(*clean_types(result)) 

e non devi ricordarti di fare nulla.