Vraag String omzetten in datetime


Kort en eenvoudig. Ik heb een enorme lijst van datum-tijden zoals deze als strings:

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

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

Alle hulp (zelfs als het slechts een schop in de goede richting is) zou worden gewaardeerd.

Bewerken: dit gaat door de ORM van Django, dus ik kan SQL niet gebruiken om de conversie op invoegen uit te voeren.


1458
2018-01-21 18:00


oorsprong


antwoorden:


datetime.strptime is de hoofdroutine voor het parseren van tekenreeksen in datimes. Het kan allerlei soorten indelingen aan, waarbij het formaat bepaald wordt door een formatstring die je het geeft:

from datetime import datetime

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

Het resultaat datetime object is tijdzone-naïef.

Links:

Opmerkingen:

  • strptime = "string parse time"
  • strftime = "string format time"
  • Spreek het vandaag hardop uit en je hoeft het niet binnen 6 maanden opnieuw te zoeken.

2396
2018-01-21 18:08



Gebruik de derde partij dateutil bibliotheek:

from dateutil import parser
dt = parser.parse("Aug 28 1999 12:00AM")

Het kan overweg met de meeste datumnotaties, inclusief degene die je moet parsen. Het is handiger dan strptime omdat het het juiste formaat meestal kan raden.

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

U kunt het installeren met:

pip install python-dateutil

623
2018-01-22 18:27



Uitchecken strptime in de tijd module. Het is het omgekeerde van strftime.

$ python
>>> import 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)

460
2018-01-21 18:07



Ik heb een project samengesteld dat sommige echt nette uitdrukkingen kan omzetten. Uitchecken 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))

87
2018-03-02 14:22



Onthoud dit en je hoefde je niet opnieuw in verwarring te brengen in datetime conversie.

String naar datetime-object = strptime

datetime-object voor andere indelingen = strftime

Jun 1 2005 1:33PM

is gelijk aan

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

% b Month as locale's afkorting name (Jun)

% d Dag van de maand als nul-gevuld decimaal getal (1)

% Y Jaar met eeuw als een decimaal getal (2015)

% I Hour (12-uursklok) als een nul gevuld decimaal getal (01)

% M Minuut als nul decimaal getal (33)

% p Locale equivalent van AM of PM (PM)

dus je hebt strptime i-e conversie nodig 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
... 

uitgang

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

Wat als je een ander datumnotatie hebt, je kunt 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]

Vermogen

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

33
2017-12-10 13:00



Veel tijdstempels hebben een geïmpliceerde tijdzone. Om ervoor te zorgen dat uw code in elke tijdzone werkt, moet u UTC intern gebruiken en een tijdzone bijvoegen telkens wanneer er een vreemd voorwerp in het systeem komt.

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

30
2018-03-06 11:53



Iets wat hier niet wordt genoemd en nuttig is: een achtervoegsel toevoegen aan de dag. Ik heb de achtervoegsellogica ontkoppeld, zodat je deze kunt gebruiken voor elk nummer dat je wilt, niet alleen 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"))​​​​​​​

21
2017-10-14 00:13



Hier zijn twee oplossingen die Panda's gebruiken om datums die zijn opgemaakt als tekenreeksen om te zetten naar objecten dieetime.date zijn.

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

En hier is hoe u de originele datum-tijd voorbeelden van het 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 to_datetime, dus controleer de docs als je iets speciaals nodig hebt.

Evenzo hebben tijdstempels veel eigenschappen en methoden die toegankelijk is als aanvulling op .date


19
2017-12-20 03:03



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 dat hebt gedaan USE_TZ = True:

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

12
2017-11-20 17:58