Wstawianie obiektu datetime.datetime w języku Python do MySQL

120

Mam kolumnę z datą w tabeli MySQL. Chcę wstawić datetime.datetime()obiekt do tej kolumny. Czego powinienem używać w instrukcji execute?

Próbowałem:

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

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

Otrzymuję komunikat o błędzie: "TypeError: not all arguments converted during string formatting" Czego należy używać zamiast %s?

Peter Mortensen
źródło
przegapiłeś cytaty wokół%s cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s , '%s')",("name", 4,now))
Sheshnath

Odpowiedzi:

198

W przypadku pola czasu użyj:

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

Myślę, że strftime dotyczy również datetime.

g33kz0r
źródło
4
Upewnij się również, że nazwa Twojej kolumny nie jest słowem zastrzeżonym . Zajęło mi 30 minut, zanim zdałem sobie sprawę, że nazwa „current_date” powoduje problemy ... ugh!
Pakman,
2
Co jest timew tym przykładzie?
James McMahon
1
J McMahon: czas to moduł Pythona.
dstromberg
A co jeśli ktoś chce pobrać jedyny rok, miesiąc, dzień?
Pooja Khatri
42

Najprawdopodobniej otrzymasz TypeError, ponieważ potrzebujesz cudzysłowów wokół wartości kolumny dat.

Próbować:

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

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

Jeśli chodzi o format, udało mi się z powyższym poleceniem (które zawiera milisekundy) i:

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

Mam nadzieję że to pomoże.

Edvinas
źródło
8
Możesz nie mieć cytatów %sw pymsql.
Martin Thoma
1
Cytaty wokół trzeciego% s powodują błąd, gdy próbuję tego.
realjin
13

Spróbuj użyć, now.date()aby uzyskać Dateobiekt, a nie plik DateTime.

Jeśli to nie zadziała, konwersja tego na ciąg znaków powinna działać:

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
źródło
Nie musisz dodawać cudzysłowów wokół parametrów ciągu, np. „... VALUES ('% s', '% s', '% s')”
Gareth Simpson,
5

Użyj metody Python datetime.strftime(format), gdzie format = '%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')))

Strefy czasowe

Jeśli problemem są strefy czasowe, strefę czasową MySQL można ustawić na czas UTC w następujący sposób:

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

Strefę czasową można ustawić w Pythonie:

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

Dokumentacja MySQL

MySQL rozpoznaje wartości DATETIME i TIMESTAMP w następujących formatach:

Jako ciąg w formacie „RRRR-MM-DD GG: MM: SS” lub „RR-MM-DD GG: MM: SS” . Również tutaj dozwolona jest „luźna” składnia: dowolny znak interpunkcyjny może być użyty jako separator między częściami daty lub częściami czasu. Na przykład „2012-12-31 11:30:45”, „2012 ^ 12 ^ 31 11 + 30 + 45”, „2012/12/31 11 * 30 * 45” i „2012 @ 12 @ 31 11 ^ 30 ^ 45 'są równoważne.

Jedynym separatorem rozpoznawanym między częścią zawierającą datę i godzinę a częścią ułamkową sekundy jest separator dziesiętny.

Części daty i godziny można oddzielić za pomocą litery T zamiast spacji. Na przykład „2012-12-31 11:30:45” „2012-12-31T11: 30: 45” są równoważne.

Jako ciąg bez separatorów w formacie „RRRRMMDDHHMMSS” lub „RRMMDDHHMMSS”, pod warunkiem, że ciąg ma sens jako data. Na przykład „20070523091528” i „070523091528” są interpretowane jako „2007-05-23 09:15:28”, ale „071122129015” jest niedozwolone (zawiera bezsensowną część minuty) i staje się „0000-00-00 00: 00:00 ”.

Jako liczba w formacie RRRRMMDDHHMMSS lub RRMMDDHHMMSS, pod warunkiem, że ma sens jako data. Na przykład 19830905132800 i 830905132800 są interpretowane jako „1983-09-05 13:28:00”.

Christopher Peisert
źródło
3

Z jaką bazą danych się łączysz? Wiem, że Oracle może być wybredny w kwestii formatów dat i lubi format ISO 8601 .

** Uwaga: Ups, właśnie przeczytałem, że jesteś na MySQL. Po prostu sformatuj datę i wypróbuj ją jako osobne bezpośrednie wywołanie SQL do przetestowania.

W Pythonie możesz uzyskać datę ISO, taką jak

now.isoformat()

Na przykład Oracle lubi takie randki jak

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

W zależności od bazy danych, jeśli jest to Oracle, może być konieczne TO_DATE:

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

Ogólne zastosowanie terminu TO_DATE to:

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

Jeśli korzystasz z innej bazy danych (widziałem kursor i pomyślałem, że Oracle; mogę się mylić), sprawdź ich narzędzia do formatowania daty. Dla MySQL jest to DATE_FORMAT (), a SQL Server to CONVERT.

Również użycie narzędzia takiego jak SQLAlchemy usunie takie różnice i ułatwi Ci życie.

Ryan Christensen
źródło
Nie polecam używania datetime.isoformat (), ponieważ jeśli używasz obiektu obsługującego strefę czasową, wygenerowany ciąg zawiera dane strefy czasowej i nie pasuje już do wymaganego formatu mysql.
frankster
0

Jeśli używasz tylko pythona datetime.date (nie pełnej daty i godziny), po prostu rzutuj datę jako ciąg. To jest bardzo proste i działa dla mnie (mysql, python 2.7, Ubuntu). Kolumna published_dateto pole daty MySQL, a zmienna Pythona publish_dateto 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
źródło
0

podczas wstawiania do t-sql

to się nie udaje:

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

to działa:

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

łatwy sposób:

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
źródło