Insertar un objeto datetime.datetime de Python en MySQL

120

Tengo una columna de fecha en una tabla MySQL. Quiero insertar un datetime.datetime()objeto en esta columna. ¿Qué debería usar en la instrucción de ejecución?

Yo he tratado:

now = datetime.datetime(2009,5,5)

cursor.execute("INSERT INTO table
(name, id, datecolumn) VALUES (%s, %s
, %s)",("name", 4,now))

Recibo un error como: "TypeError: not all arguments converted during string formatting" ¿Qué debo usar en lugar de %s?

Peter Mortensen
fuente
te perdiste las citas%s cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s , '%s')",("name", 4,now))
Sheshnath

Respuestas:

198

Para un campo de tiempo, use:

import time    
time.strftime('%Y-%m-%d %H:%M:%S')

Creo que strftime también se aplica a datetime.

g33kz0r
fuente
4
Además, asegúrese de que el nombre de su columna no sea una palabra reservada . Me tomó 30 minutos darme cuenta de que el nombre "current_date" estaba causando problemas ... ¡uf!
Pakman
2
¿Qué hay timeen este ejemplo?
James McMahon
1
J McMahon: el tiempo es un módulo de Python.
dstromberg
¿Qué pasa si alguien quiere buscar el único año, mes, día?
Pooja Khatri
42

Lo más probable es que obtenga TypeError porque necesita comillas alrededor del valor de la columna de fecha.

Tratar:

now = datetime.datetime(2009, 5, 5)

cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s, '%s')",
               ("name", 4, now))

Con respecto al formato, tuve éxito con el comando anterior (que incluye los milisegundos) y con:

now.strftime('%Y-%m-%d %H:%M:%S')

Espero que esto ayude.

Edvinas
fuente
8
Puede que no tenga comillas %sen pymsql.
Martin Thoma
1
Las citas alrededor del tercer% s provocan un error cuando intento esto.
realjin
13

Intente usar now.date()para obtener un Dateobjeto en lugar de un DateTime.

Si eso no funciona, convertirlo en una cadena debería funcionar:

now = datetime.datetime(2009,5,5)
str_now = now.date().isoformat()
cursor.execute('INSERT INTO table (name, id, datecolumn) VALUES (%s,%s,%s)', ('name',4,str_now))
Wogan
fuente
¿No es necesario agregar comillas alrededor de los parámetros de la cadena, es decir, "... VALUES ('% s', '% s', '% s')"
Gareth Simpson
5

Utilice el método Python datetime.strftime(format), donde formato = '%Y-%m-%d %H:%M:%S'.

import datetime

now = datetime.datetime.utcnow()

cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s, %s)",
               ("name", 4, now.strftime('%Y-%m-%d %H:%M:%S')))

Zonas horarias

Si las zonas horarias son una preocupación, la zona horaria de MySQL se puede configurar para UTC de la siguiente manera:

cursor.execute("SET time_zone = '+00:00'")

Y la zona horaria se puede configurar en Python:

now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)

Documentación de MySQL

MySQL reconoce los valores DATETIME y TIMESTAMP en estos formatos:

Como una cadena en formato 'AAAA-MM-DD HH: MM: SS' o 'AA-MM-DD HH: MM: SS' . Aquí también se permite una sintaxis “relajada”: cualquier carácter de puntuación puede usarse como delimitador entre partes de fecha o partes de tiempo. Por ejemplo, '2012-12-31 11:30:45', '2012 ^ 12 ^ 31 11 + 30 + 45', '2012/12/31 11 * 30 * 45' y '2012 @ 12 @ 31 11 ^ 30 ^ 45 'son equivalentes.

El único delimitador reconocido entre una parte de fecha y hora y una fracción de segundos es el punto decimal.

Las partes de fecha y hora pueden estar separadas por una T en lugar de un espacio. Por ejemplo, '2012-12-31 11:30:45' '2012-12-31T11: 30: 45' son equivalentes.

Como una cadena sin delimitadores en formato 'AAAAMMDDHHMMSS' o 'AAMMDDHHMMSS', siempre que la cadena tenga sentido como fecha. Por ejemplo, '20070523091528' y '070523091528' se interpretan como '2007-05-23 09:15:28', pero '071122129015' es ilegal (tiene una parte de minutos sin sentido) y se convierte en '0000-00-00 00: 00:00 '.

Como un número en formato AAAAMMDDHHMMSS o AAMMDDHHMMSS, siempre que el número tenga sentido como fecha. Por ejemplo, 19830905132800 y 830905132800 se interpretan como '1983-09-05 13:28:00'.

Christopher Peisert
fuente
3

¿A qué base de datos se está conectando? Sé que Oracle puede ser exigente con los formatos de fecha y le gusta el formato ISO 8601 .

** Nota: Vaya, acabo de leer que estás en MySQL. Simplemente formatee la fecha y pruébelo como una llamada SQL directa separada para probar.

En Python, puede obtener una fecha ISO como

now.isoformat()

Por ejemplo, a Oracle le gustan las fechas como

insert into x values(99, '31-may-09');

Dependiendo de su base de datos, si es Oracle, es posible que deba TO_DATE:

insert into x
values(99, to_date('2009/05/31:12:00:00AM', 'yyyy/mm/dd:hh:mi:ssam'));

El uso general de TO_DATE es:

TO_DATE(<string>, '<format>')

Si usa otra base de datos (vi el cursor y pensé en Oracle; podría estar equivocado), verifique sus herramientas de formato de fecha. Para MySQL es DATE_FORMAT () y SQL Server es CONVERT.

Además, el uso de una herramienta como SQLAlchemy eliminará diferencias como estas y le facilitará la vida.

Ryan Christensen
fuente
No recomiendo usar datetime.isoformat () porque si usa un objeto consciente de la zona horaria, la cadena generada incluye datos de la zona horaria y ya no coincide con el formato mysql requerido.
frankster
0

Si solo está usando un datetime.date de python (no un datetime.datetime completo), simplemente transmita la fecha como una cadena. Esto es muy simple y me funciona (mysql, python 2.7, Ubuntu). La columna published_datees un campo de fecha de MySQL, la variable de Python publish_datees datetime.date.

# make the record for the passed link info
sql_stmt = "INSERT INTO snippet_links (" + \
    "link_headline, link_url, published_date, author, source, coco_id, link_id)" + \
    "VALUES(%s, %s, %s, %s, %s, %s, %s) ;"

sql_data = ( title, link, str(publish_date), \
             author, posted_by, \
             str(coco_id), str(link_id) )

try:
    dbc.execute(sql_stmt, sql_data )
except Exception, e:
    ...
jbartas
fuente
0

al ejecutar en t-sql

esto falla:

select CONVERT(datetime,'2019-09-13 09:04:35.823312',21)

esto funciona:

select CONVERT(datetime,'2019-09-13 09:04:35.823',21)

manera fácil:

regexp = re.compile(r'\.(\d{6})')
def to_splunk_iso(dt):
    """Converts the datetime object to Splunk isoformat string."""
    # 6-digits string.
    microseconds = regexp.search(dt).group(1)
    return regexp.sub('.%d' % round(float(microseconds) / 1000), dt)
Krzysztof Drewicz
fuente