Konwertowanie łańcucha do datetime

Mam ogromną listę dat-czasów takich jak ten jako ciągi:

Jun 1 2005  1:33PM
Aug 28 1999 12:00AM

Zamierzam wepchnąć je z powrotem do odpowiednich pól datetime w bazie danych, więc muszę zaczarować je w prawdziwe obiekty datetime.

To przechodzi przez ORM Django, więc nie mogę użyć SQL do konwersji na insert.

Author: halfer, 2009-01-21

22 answers

datetime.strptime jest główną rutyną do parsowania łańcuchów do dat. Może obsługiwać wszystkie rodzaje formatów, z formatem określonym przez ciąg formatów, który mu podasz:

from datetime import datetime

datetime_object = datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

Wynikowy obiekt datetime nie ma strefy czasowej.

Linki:

Uwagi:

  • strptime = "string parse time"
  • strftime = "string format time"
  • Wymów go na głos dzisiaj i nie będziesz musiał szukać go ponownie w ciągu 6 miesięcy.
 3711
Author: Patrick Harrington,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-28 06:17:54

Użyj trzeciej strony dateutil biblioteka:

from dateutil import parser
parser.parse("Aug 28 1999 12:00AM")  # datetime.datetime(1999, 8, 28, 0, 0)

Może obsługiwać większość formatów dat, w tym ten, który musisz przeanalizować. Jest to wygodniejsze niż strptime, ponieważ potrafi odgadnąć poprawny format przez większość czasu.

Jest bardzo przydatny do pisania testów, gdzie czytelność jest ważniejsza niż wydajność.

Można go zainstalować za pomocą:

pip install python-dateutil
 896
Author: Simon Willison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-08 23:20:42

Sprawdź strptime w moduletime . Jest odwrotnością strftime .

$ python
>>> import time
>>> my_time = time.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')
time.struct_time(tm_year=2005, tm_mon=6, tm_mday=1,
                 tm_hour=13, tm_min=33, tm_sec=0,
                 tm_wday=2, tm_yday=152, tm_isdst=-1)

timestamp = time.mktime(my_time)
# convert time object to datetime
from datetime import datetime
my_datetime = datetime.fromtimestamp(timestamp)
# convert time object to date
from datetime import date
my_date = date.fromtimestamp(timestamp)
 498
Author: florin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-07 22:11:43

Przygotowałem projekt, który potrafi konwertować naprawdę fajne wyrażenia. Zobacz też timestring.

Oto kilka przykładów poniżej:

pip install timestring
>>> import timestring
>>> timestring.Date('monday, aug 15th 2015 at 8:40 pm')
<timestring.Date 2015-08-15 20:40:00 4491909392>
>>> timestring.Date('monday, aug 15th 2015 at 8:40 pm').date
datetime.datetime(2015, 8, 15, 20, 40)
>>> timestring.Range('next week')
<timestring.Range From 03/10/14 00:00:00 to 03/03/14 00:00:00 4496004880>
>>> (timestring.Range('next week').start.date, timestring.Range('next week').end.date)
(datetime.datetime(2014, 3, 10, 0, 0), datetime.datetime(2014, 3, 14, 0, 0))
 120
Author: Steve Peak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Python > = 3.7

Aby przekonwertować RRRR-MM-DD string na obiekt datetime, można użyć datetime.fromisoformat.

>>> from datetime import datetime

>>> date_string = "2012-12-12 10:10:10"
>>> print (datetime.fromisoformat(date_string))
>>> 2012-12-12 10:10:10
 66
Author: SuperNova,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-24 08:45:39

Pamiętaj o tym i nie musisz się ponownie mylić w konwersji datetime.

String to datetime object = strptime

Obiekt Datetime do innych formatów = strftime

Jun 1 2005 1:33PM

Jest równe

%b %d %Y %I:%M%p

% B miesiąc jako skrócona nazwa locale (Jun)

%D dnia miesiąca jako liczba dziesiętna (1)

%rok z wiekiem jako liczbą dziesiętną(2015)

%i godzina (Zegar 12-godzinny) jako liczba dziesiętna zerowa (01)

% m minuta jako liczba dziesiętna (33)

% P odpowiednik lokalnego AM lub PM (PM)

Więc potrzebujesz konwersji strptime i-E string na

>>> dates = []
>>> dates.append('Jun 1 2005  1:33PM')
>>> dates.append('Aug 28 1999 12:00AM')
>>> from datetime import datetime
>>> for d in dates:
...     date = datetime.strptime(d, '%b %d %Y %I:%M%p')
...     print type(date)
...     print date
... 

Wyjście

<type 'datetime.datetime'>
2005-06-01 13:33:00
<type 'datetime.datetime'>
1999-08-28 00:00:00

Co jeśli masz inny format dat, możesz użyć panda lub dateutil.parse

>>> import dateutil
>>> dates = []
>>> dates.append('12 1 2017')
>>> dates.append('1 1 2017')
>>> dates.append('1 12 2017')
>>> dates.append('June 1 2017 1:30:00AM')
>>> [parser.parse(x) for x in dates]

Wyjście

[datetime.datetime(2017, 12, 1, 0, 0), datetime.datetime(2017, 1, 1, 0, 0), datetime.datetime(2017, 1, 12, 0, 0), datetime.datetime(2017, 6, 1, 1, 30)]
 56
Author: Rizwan Mumtaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-30 07:20:19

Wiele znaczników czasu ma domyślną strefę czasową. Aby mieć pewność, że Twój kod będzie działał w każdej strefie czasowej, powinieneś użyć UTC wewnętrznie i dołączyć strefę czasową za każdym razem, gdy obcy obiekt wejdzie do systemu.

Python 3.2+:

>>> datetime.datetime.strptime(
...     "March 5, 2014, 20:13:50", "%B %d, %Y, %H:%M:%S"
... ).replace(tzinfo=datetime.timezone(datetime.timedelta(hours=-3)))
 34
Author: Janus Troelsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-05 12:34:58

Oto dwa rozwiązania wykorzystujące pandy do konwersji dat sformatowanych jako ciągi znaków na datetime.obiekty daty.

import pandas as pd

dates = ['2015-12-25', '2015-12-26']

# 1) Use a list comprehension.
>>> [d.date() for d in pd.to_datetime(dates)]
[datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)]

# 2) Convert the dates to a DatetimeIndex and extract the python dates.
>>> pd.DatetimeIndex(dates).date.tolist()
[datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)]

Timings

dates = pd.DatetimeIndex(start='2000-1-1', end='2010-1-1', freq='d').date.tolist()

>>> %timeit [d.date() for d in pd.to_datetime(dates)]
# 100 loops, best of 3: 3.11 ms per loop

>>> %timeit pd.DatetimeIndex(dates).date.tolist()
# 100 loops, best of 3: 6.85 ms per loop

A oto jak przekonwertować oryginalne przykłady daty i czasu OP:

datetimes = ['Jun 1 2005  1:33PM', 'Aug 28 1999 12:00AM']

>>> pd.to_datetime(datetimes).to_pydatetime().tolist()
[datetime.datetime(2005, 6, 1, 13, 33), 
 datetime.datetime(1999, 8, 28, 0, 0)]

Istnieje wiele opcji konwersji z łańcuchów na znaczniki czasu Pandy za pomocą to_datetime, więc sprawdź docs jeśli potrzebujesz czegoś specjalnego.

Podobnie znaczniki czasu mają wiele właściwości i metod , które można uzyskać w dodatek do .date

 31
Author: Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-02 07:08:49

Osobiście podoba mi się rozwiązanie za pomocą modułu parser, który jest drugą odpowiedzią na to pytanie i jest piękny, ponieważ nie trzeba konstruować żadnych liter ciągów, aby to działało. ale , jednym minusem jest to, że jest ona 90% wolniejsza niż przyjęta odpowiedź z strptime.

from dateutil import parser
from datetime import datetime
import timeit

def dt():
    dt = parser.parse("Jun 1 2005  1:33PM")
def strptime():
    datetime_object = datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

print(timeit.timeit(stmt=dt, number=10**5))
print(timeit.timeit(stmt=strptime, number=10**5))
>10.70296801342902
>1.3627995655316933

Dopóki nie robisz tego milion razy w kółko, nadal uważam, że metoda parser jest wygodniejsza i obsłuży większość formatów czasu automatycznie.

 26
Author: user1767754,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-01 01:50:18

Coś, co nie jest tutaj wymienione i jest przydatne: dodanie sufiksu do dnia. Oddzieliłem logikę przyrostka, żebyś mógł go używać dla dowolnej liczby, nie tylko dat.

import time

def num_suffix(n):
    '''
    Returns the suffix for any given int
    '''
    suf = ('th','st', 'nd', 'rd')
    n = abs(n) # wise guy
    tens = int(str(n)[-2:])
    units = n % 10
    if tens > 10 and tens < 20:
        return suf[0] # teens with 'th'
    elif units <= 3:
        return suf[units]
    else:
        return suf[0] # 'th'

def day_suffix(t):
    '''
    Returns the suffix of the given struct_time day
    '''
    return num_suffix(t.tm_mday)

# Examples
print num_suffix(123)
print num_suffix(3431)
print num_suffix(1234)
print ''
print day_suffix(time.strptime("1 Dec 00", "%d %b %y"))
print day_suffix(time.strptime("2 Nov 01", "%d %b %y"))
print day_suffix(time.strptime("3 Oct 02", "%d %b %y"))
print day_suffix(time.strptime("4 Sep 03", "%d %b %y"))
print day_suffix(time.strptime("13 Nov 90", "%d %b %y"))
print day_suffix(time.strptime("14 Oct 10", "%d %b %y"))​​​​​​​
 24
Author: Aram Kocharyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-14 00:28:40
In [34]: import datetime

In [35]: _now = datetime.datetime.now()

In [36]: _now
Out[36]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)

In [37]: print _now
2016-01-19 09:47:00.432000

In [38]: _parsed = datetime.datetime.strptime(str(_now),"%Y-%m-%d %H:%M:%S.%f")

In [39]: _parsed
Out[39]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)

In [40]: assert _now == _parsed
 18
Author: guneysus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-19 07:48:47

Django timezone aware DateTime object przykład.

import datetime
from django.utils.timezone import get_current_timezone
tz = get_current_timezone()

format = '%b %d %Y %I:%M%p'
date_object = datetime.datetime.strptime('Jun 1 2005  1:33PM', format)
date_obj = tz.localize(date_object)

Ta konwersja jest bardzo ważna dla Django i Pythona, gdy masz USE_TZ = True:

RuntimeWarning: DateTimeField MyModel.created received a naive datetime (2016-03-04 00:00:00) while time zone support is active.
 16
Author: Ryu_hayabusa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-03 13:44:40

Przydałby się do konwersji łańcucha znaków do datetime, a także ze strefą czasową

def convert_string_to_time(date_string, timezone):
    from datetime import datetime
    import pytz
    date_time_obj = datetime.strptime(date_string[:26], '%Y-%m-%d %H:%M:%S.%f')
    date_time_obj_timezone = pytz.timezone(timezone).localize(date_time_obj)

    return date_time_obj_timezone

date = '2018-08-14 13:09:24.543953+00:00'
TIME_ZONE = 'UTC'
date_time_obj_timezone = convert_string_to_time(date, TIME_ZONE)
 14
Author: Kanish Mathew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-30 05:49:20

Tworzenie małej funkcji użytkowej jak:

def date(datestr="", format="%Y-%m-%d"):
    from datetime import datetime
    if not datestr:
        return datetime.today().date()
    return datetime.strptime(datestr, format).date()

To jest wystarczająco uniwersalne:

  • Jeśli nie podasz żadnych argumentów, zwróci dzisiejszą datę.
  • istnieje domyślny format daty, który możesz zastąpić.
  • można go łatwo zmodyfikować, aby zwrócić datetime.
 12
Author: Mackraken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 23:00:23

Arrow oferuje wiele przydatnych funkcji dla dat i godzin. Ten fragment kodu zapewnia odpowiedź na pytanie i pokazuje, że arrow jest również w stanie łatwo formatować daty i wyświetlać informacje dla innych lokalizacji.

>>> import arrow
>>> dateStrings = [ 'Jun 1  2005 1:33PM', 'Aug 28 1999 12:00AM' ]
>>> for dateString in dateStrings:
...     dateString
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').datetime
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').format('ddd, Do MMM YYYY HH:mm')
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').humanize(locale='de')
...
'Jun 1  2005 1:33PM'
datetime.datetime(2005, 6, 1, 13, 33, tzinfo=tzutc())
'Wed, 1st Jun 2005 13:33'
'vor 11 Jahren'
'Aug 28 1999 12:00AM'
datetime.datetime(1999, 8, 28, 0, 0, tzinfo=tzutc())
'Sat, 28th Aug 1999 00:00'
'vor 17 Jahren'

Zobacz http://arrow.readthedocs.io/en/latest / Po Więcej.

 10
Author: Bill Bell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 23:02:32

Możesz użyć easy_date aby to ułatwić:

import date_converter
converted_date = date_converter.string_to_datetime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')
 6
Author: Raphael Amoedo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-01 15:15:02

Jeśli chcesz tylko format daty, możesz ręcznie przekonwertować go, przekazując poszczególne pola, takie jak:

>>> import datetime
>>> date = datetime.date(int('2017'),int('12'),int('21'))
>>> date
datetime.date(2017, 12, 21)
>>> type(date)
<type 'datetime.date'>

Możesz przekazać podzieloną wartość łańcuchową, aby przekonwertować ją na typ daty, taki jak:

selected_month_rec = '2017-09-01'
date_formate = datetime.date(int(selected_month_rec.split('-')[0]),int(selected_month_rec.split('-')[1]),int(selected_month_rec.split('-')[2]))

Uzyskasz wartość w formacie daty.

 4
Author: Javed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 23:04:32

Możesz również sprawdzić dateparser

dateparser dostarcza moduły do łatwego analizowania zlokalizowanych dat w prawie wszelkie formaty ciągów powszechnie spotykane na stronach internetowych.

zainstaluj:

$ pip install dateparser

To chyba najprostszy sposób na analizę dat.

Najprostszym sposobem jest użycie funkcji dateparser.parse, to owija się wokół większości funkcji w module.

próbka Kod:

import dateparser

t1 = 'Jun 1 2005  1:33PM'
t2 = 'Aug 28 1999 12:00AM'

dt1 = dateparser.parse(t1)
dt2 = dateparser.parse(t2)

print(dt1)
print(dt2)

Wyjście:

2005-06-01 13:33:00
1999-08-28 00:00:00
 4
Author: Bilesh Ganguly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-12 17:55:16

Jeśli twój ciąg znaków jest w formacie ISO8601 i masz Pythona 3.7+, możesz użyć następującego prostego kodu:

import datetime.date

aDate = datetime.date.fromisoformat('2020-10-04')

Dla dat i

import datetime.datetime

aDateTime = datetime.datetime.fromisoformat('2020-10-04 22:47:00')

Dla łańcuchów zawierających datę i czas. Jeśli znaczniki czasu są włączone, funkcja datetime.datetime.isoformat() obsługuje następujący format

YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]

Gdzie * pasuje do dowolnego pojedynczego znaku. Zobacz także tutaj i tutaj

 3
Author: jjm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-04 20:57:05

Zobacz moja odpowiedź .

W rzeczywistych danych jest to prawdziwy problem: wiele, niedopasowanych, niekompletnych, niespójnych i wielojęzycznych/regionalnych formatów dat, często mieszanych swobodnie w jednym zbiorze danych. Nie jest w porządku, żeby kod produkcyjny zawodził, nie mówiąc już o wyjątkach-szczęśliwy jak lis.

Musimy spróbować...przechwytywanie wielu formatów datetime fmt1, fmt2,..., fmtn i tłumią/obsługują wyjątki (od strptime()) dla wszystkich tych, które nie pasują (a w szczególności unikają konieczności wcięta drabina próby..klauzule połowu). Z moje rozwiązanie
def try_strptime(s, fmts=['%d-%b-%y','%m/%d/%Y']):
    for fmt in fmts:
        try:
            return datetime.strptime(s, fmt)
        except:
            continue

    return None # or reraise the ValueError if no format matched, if you prefer
 1
Author: smci,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-05 15:52:25
emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv")
emp.info()

Pokazuje kolumnę " Data rozpoczęcia czasu "i" czas ostatniego logowania "obie są" obiekt = ciągi " w ramce danych

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 8 columns):
First Name           933 non-null object
Gender               855 non-null object
Start Date           1000 non-null object

Last Login Time      1000 non-null object
Salary               1000 non-null int64
Bonus %              1000 non-null float64
Senior Management    933 non-null object
Team                 957 non-null object
dtypes: float64(1), int64(1), object(6)
memory usage: 62.6+ KB

Za pomocą parse_dates opcja w read_csv wspomnieć można przekonwertować swój łańcuch datetime do formatu datetime pandy.

emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv", parse_dates=["Start Date", "Last Login Time"])
emp.info()


<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 8 columns):
First Name           933 non-null object
Gender               855 non-null object
Start Date           1000 non-null datetime64[ns]
Last Login Time      1000 non-null datetime64[ns]
Salary               1000 non-null int64
Bonus %              1000 non-null float64
Senior Management    933 non-null object
Team                 957 non-null object
dtypes: datetime64[ns](2), float64(1), int64(1), object(4)
memory usage: 62.6+ KB
 1
Author: Riz.Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-01 12:17:51

Wydaje się, że użycie znacznika czasu pandas jest najszybsze

import pandas as pd 

N = 1000

l = ['Jun 1 2005  1:33PM'] * N

list(pd.to_datetime(l, format=format))

%timeit _ = list(pd.to_datetime(l, format=format))
1.58 ms ± 21.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Inne rozwiązania

from datetime import datetime
%timeit _ = list(map(lambda x: datetime.strptime(x, format), l))
9.41 ms ± 95.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

from dateutil.parser import parse
%timeit _ = list(map(lambda x: parse(x), l))
73.8 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Jeśli ciąg jest iso8601 string Proszę użyć csio8601

import ciso8601

l = ['2014-01-09'] * N

%timeit _ = list(map(lambda x: ciso8601.parse_datetime(x), l))
186 µs ± 4.13 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
 0
Author: Grzegorz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-29 07:09:40