Tekenreeks converteren naar datetime

Ik heb een enorme lijst van datum-tijden als deze als strings:

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

Ik ga deze terugzetten in de juiste datetime-velden in een database, dus ik moet ze toveren in echte datetime-objecten.

Dit gaat via de ORM van Django, dus ik kan geen SQL gebruiken om de conversie bij invoegen uit te voeren.


Antwoord 1, autoriteit 100%

datetime.strptime is de belangrijkste routine voor het ontleden van strings in datetimes. Het kan alle soorten formaten aan, waarbij het formaat bepaald wordt door een format string die je eraan geeft:

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

Het resulterende datetime object is tijdzone-naïef.

Links:

Opmerkingen:

  • strptime = “string parseertijd”
  • strftime = “tekenreeksnotatietijd”
  • Spreek het vandaag hardop uit & u hoeft er over 6 maanden niet meer naar te zoeken.

Antwoord 2, autoriteit 24%

Gebruik de dateutil bibliotheek van derden:

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

Het kan de meeste datumformaten aan, inclusief degene die je moet ontleden. Het is handiger dan strptime omdat het meestal het juiste formaat kan raden.

Het is erg handig voor het schrijven van tests, waarbij leesbaarheid belangrijker is dan prestaties.

Je kunt het installeren met:

pip install python-dateutil

Antwoord 3, autoriteit 13%

Bekijk strptime in de time-module. Het is het omgekeerde van 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)

Antwoord 4, autoriteit 3%

Ik heb een project samengesteld dat een aantal echt nette uitdrukkingen kan converteren. Bekijk timestring.

Hier zijn enkele voorbeelden hieronder:

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))

Antwoord 5, autoriteit 2%

python >= 3.7

om de tekenreeks JJJJ-MM-DD te converteren naar datetime-object, kan datetime.fromisoformat worden gebruikt.

from datetime import datetime
date_string = "2012-12-12 10:10:10"
print (datetime.fromisoformat(date_string))
2012-12-12 10:10:10

Antwoord 6

Onthoud dit en u hoefde niet opnieuw in de war te raken over datetime-conversie.

String naar datetime object = strptime

datetime-object naar andere formaten = strftime

Jun 1 2005 1:33PM

is gelijk aan

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

%b maand als afgekorte naam van de landinstelling (juni)

%d Dag van de maand als decimaal getal met nulpunten(1)

%Y Jaar met eeuw als decimaal getal (2015)

%I Uur (12-uurs klok) als decimaal getal met nulpunt(01)

%M Minuut als een decimaal getal met nulpunt (33)

%p Landequivalent van AM of PM(PM)

dus je moet strptime i-e omzetten van string naar

>>> 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
... 

Uitvoer

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

Als je een ander datumformaat hebt, kun je panda of dateutil.parse gebruiken

>>> 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]

Uitvoer

[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)]

Antwoord 7

Veel tijdstempels hebben een impliciete tijdzone. Om ervoor te zorgen dat uw code in elke tijdzone werkt, moet u intern UTC gebruiken en een tijdzone toevoegen telkens wanneer een vreemd object het systeem binnenkomt.

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)))

Hierbij wordt ervan uitgegaan dat u de offset kent. Als je dat niet doet, maar je weet b.v. de locatie, kunt u het pakket pytz gebruiken om de IANA-tijdzonedatabase voor de offset. Ik zal Teheran hier als voorbeeld gebruiken, omdat het een verschuiving van een half uur heeft:

>>> tehran = pytz.timezone("Asia/Tehran")
>>> local_time = tehran.localize(
...   datetime.datetime.strptime("March 5, 2014, 20:13:50",
...                              "%B %d, %Y, %H:%M:%S")
... )
>>> local_time
datetime.datetime(2014, 3, 5, 20, 13, 50, tzinfo=<DstTzInfo 'Asia/Tehran' +0330+3:30:00 STD>)

Zoals je kunt zien, heeft pytz vastgesteld dat de offset +3:30 was op die specifieke datum. U kunt dit nu converteren naar UTC-tijd, en het zal de offset toepassen:

>>> utc_time = local_time.astimezone(pytz.utc)
>>> utc_time
datetime.datetime(2014, 3, 5, 16, 43, 50, tzinfo=<UTC>)

Houd er rekening mee dat datums vóór de invoering van tijdzones rare verschuivingen zullen opleveren. Dit komt omdat de IANA heeft besloten om Local Mean Time:

te gebruiken

>>> chicago = pytz.timezone("America/Chicago")
>>> weird_time = chicago.localize(
...   datetime.datetime.strptime("November 18, 1883, 11:00:00",
...                              "%B %d, %Y, %H:%M:%S")
... )
>>> weird_time.astimezone(pytz.utc)
datetime.datetime(1883, 11, 18, 7, 34, tzinfo=<UTC>)

De vreemde 34 seconden zijn afgeleid van de lengtegraad van Chicago. Ik heb deze datum gebruikt omdat het de dag is waarop de gestandaardiseerde tijd geadopteerd in Chicago.


Antwoord 8

Hier zijn twee oplossingen die Panda’s gebruiken om datums die zijn opgemaakt als strings om te zetten in datetime.date-objecten.

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)]

Timingen

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

En hier is hoe je de originele datum-tijd-voorbeelden van de OP kunt converteren:

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)]

Er zijn veel opties voor het converteren van de tekenreeksen naar Pandas-tijdstempels met behulp van to_datetime, dus controleer de docs als je iets speciaals nodig hebt.

Evenzo hebben tijdstempels veel eigenschappen en methoden die toegankelijk zijn naast .date


Antwoord 9

Persoonlijk vind ik de oplossing met behulp van de module parser het tweede antwoord op deze vraag en mooi, omdat je geen letterlijke tekenreeksen hoeft te construeren om het werkend te krijgen. MAAR, een nadeel is dat het 90% langzamer is dan het geaccepteerde antwoord met 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

Zolang je dit niet een miljoen keer keer op keer doet, denk ik nog steeds dat de parser-methode handiger is en de meeste tijdformaten zal verwerken automatisch.


Antwoord 10

Iets dat hier niet wordt genoemd en handig is: een achtervoegsel aan de dag toevoegen. Ik heb de achtervoegsellogica ontkoppeld, zodat je het kunt gebruiken voor elk nummer dat je wilt, niet alleen voor datums.

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"))???????

Antwoord 11

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

Antwoord 12

Django Timezone bewust datetime object voorbeeld.

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)

Deze conversie is erg belangrijk voor Django en Python als je USE_TZ = True:

hebt

RuntimeWarning: DateTimeField MyModel.created received a naive datetime (2016-03-04 00:00:00) while time zone support is active.

Antwoord 13

Het zou nuttig zijn voor het converteren van string naar datetime en ook met tijdzone

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)

Antwoord 14

Maak een kleine hulpprogramma-functie zoals:

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

Dit is veelzijdig genoeg:

  • Als je geen argumenten doorgeeft, wordt de datum van vandaag teruggegeven.
  • Er is standaard een datumnotatie die u kunt overschrijven.
  • Je kunt het gemakkelijk aanpassen om een ​​datum/tijd terug te geven.

Antwoord 15

pijl biedt veel handige functies voor datums en tijden. Dit stukje code geeft een antwoord op de vraag en laat zien dat pijl ook in staat is om datums gemakkelijk op te maken en informatie voor andere landen weer te geven.

>>> 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'

Zie http://arrow.readthedocs.io/en/latest/ voor meer.


Antwoord 16

Als je string de ISO8601-indeling heeft en je Python 3.7+ hebt, kun je de volgende eenvoudige code gebruiken:

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

voor datums en

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

voor tekenreeksen die datum en tijd bevatten. Als tijdstempels zijn opgenomen, ondersteunt de functie datetime.datetime.isoformat() het volgende formaat

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

waar * overeenkomt met een enkel teken. Zie ook hier en hier


Antwoord 17

Je kunt easy_date gebruiken om het gemakkelijk te maken:

import date_converter
converted_date = date_converter.string_to_datetime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

Antwoord 18

Je kunt ook dateparser

bekijken

dateparser biedt modules om gemakkelijk gelokaliseerde datums in bijna
alle tekenreeksen die vaak op webpagina’s worden aangetroffen.

Installeren:

$ pip install dateparser

Dit is, denk ik, de gemakkelijkste manier om datums te ontleden.

De eenvoudigste manier is om de functie dateparser.parse te gebruiken,
die de meeste functionaliteit in de module omvat.

Voorbeeldcode:

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)

Uitvoer:

2005-06-01 13:33:00
1999-08-28 00:00:00

Antwoord 19

Als u alleen de datumnotatie wilt, kunt u deze handmatig converteren door uw individuele velden door te geven, zoals:

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

U kunt uw gesplitste tekenreekswaarden doorgeven om deze om te zetten in een datumtype zoals:

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]))

U krijgt de resulterende waarde in datumnotatie.


Antwoord 20

Zie mijn antwoord .

In real-world data is dit een reëel probleem: meerdere, niet-overeenkomende, onvolledige, inconsistente en meertalige/regionale datumnotaties, vaak vrijelijk gemengd in één dataset. Het is niet oké dat de productiecode faalt, laat staan ​​dat je uitzonderlijk blij wordt als een vos.

We moeten proberen…meerdere datum/tijd-formaten fmt1,fmt2,…,fmtn te vinden en de uitzonderingen (van strptime()) te onderdrukken/af te handelen voor al degenen die niet overeenkomen (en in in het bijzonder, vermijd het gebruik van een yukky n-diep ingesprongen ladder van try..catch-clausules). Van mijn oplossing

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

Antwoord 21

emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv")
emp.info()

het toont de kolom “Startdatum tijd” en “Laatste inlogtijd” beide zijn “object = strings” in dataframe

<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

Door de parse_dates optie in de read_csv vermelding te gebruiken, kun je je string datetime converteren naar panda’s datetime formaat.

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

Antwoord 22

Het lijkt erop dat pandas Timestamp is de snelste

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)

Andere oplossingen

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)

Als de tekenreeks een ISO8601-tekenreeks is, gebruik dan 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)

Antwoord 23

Een kort voorbeeld dat een jjjj-mm-dd datumtekenreeks toewijst aan een datetime.date-object:

from datetime import date
date_from_yyyy_mm_dd = lambda ? : date(*[int(_) for _ in ?.split('-')])
date_object = date_from_yyyy_mm_dd('2021-02-15')

Antwoord 24

Het wordt ingewikkeld als je geen specifiek patroon in de hele lijst hebt, maar als je wel een patroon hebt en je de onbewerkte tekenreeks wilt converteren naar een datetime-object. dan kan de volgende code helpen, hoewel andere vrienden het ook hebben genoemd.
panda’s importeren als pd

dates = ['2021-10-15', '2022-10-16', '2024-10-16']
dates_1 = [d.date() for d in pd.to_datetime(dates)]
for date in dates_1:
    print(date)

Om ervoor te zorgen dat alles goed werkt. je moet misschien een parser maken.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes