Question Conversion de chaîne en date-heure


Court et simple. J'ai une énorme liste de dates comme celle-ci:

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

Je vais les replacer dans des champs datetime corrects dans une base de données, j'ai donc besoin de les transformer en objets datetime réels.

Toute aide (même si c'est juste un coup de pied dans la bonne direction) serait appréciée.

Edit: Cela passe par l'ORM de Django, donc je ne peux pas utiliser SQL pour faire la conversion sur insert.


1458
2018-01-21 18:00


origine


Réponses:


datetime.strptime est la routine principale pour l'analyse des chaînes en datetime. Il peut gérer toutes sortes de formats, avec le format déterminé par une chaîne de format que vous lui donnez:

from datetime import datetime

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

La résultante datetime objet est naïf de fuseau horaire.

Liens:

Remarques:

  • strptime = "string parse time"
  • strftime = "format de chaîne de caractères"
  • Prononcez-le à haute voix aujourd'hui et vous n'aurez plus à le chercher dans 6 mois.

2396
2018-01-21 18:08



Utilisez la troisième partie dateutil bibliothèque:

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

Il peut gérer la plupart des formats de date, y compris celui que vous devez analyser. C'est plus pratique que strptime car il peut deviner le bon format la plupart du temps.

C'est très utile pour écrire des tests, où la lisibilité est plus importante que la performance.

Vous pouvez l'installer avec:

pip install python-dateutil

623
2018-01-22 18:27



Check-out strptime dans le temps module. C'est l'inverse de 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



J'ai mis en place un projet qui peut convertir des expressions vraiment soignées. Check-out timestring.

Voici quelques exemples ci-dessous:

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



Souvenez-vous de cela et vous n'avez pas eu besoin de vous perdre dans la conversion de date / heure.

Chaîne à l'objet datetime = strptime

objet datetime aux autres formats = strftime

Jun 1 2005 1:33PM

est égal à

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

% b Mois en tant que nom abrégé de l'environnement local (juin)

% d Jour du mois en tant que nombre décimal à remplissage nul (1)

% Y Année avec le siècle comme nombre décimal (2015)

% I Heure (horloge de 12 heures) en tant que nombre décimal à remplissage nul (01)

% M Minute en tant que nombre décimal à remplissage nul (33)

% p Équivalent local de AM ou PM (PM)

donc vous avez besoin de convertir i-e strptime string à

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

Sortie

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

Que faire si vous avez un format différent de dates que vous pouvez utiliser panda ou 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]

Sortie

[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



Beaucoup d'horodatages ont un fuseau horaire implicite. Pour vous assurer que votre code fonctionnera dans chaque fuseau horaire, vous devez utiliser l'UTC en interne et attacher un fuseau horaire chaque fois qu'un objet étranger entre dans le système.

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



Quelque chose qui n'est pas mentionné ici et qui est utile: ajouter un suffixe à la journée. J'ai découplé la logique du suffixe afin que vous puissiez l'utiliser pour n'importe quel nombre que vous aimez, pas seulement les dates.

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



Voici deux solutions utilisant Pandas pour convertir des dates formatées en chaînes dans des objets datetime.date.

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

Et voici comment convertir les exemples de date-heure d'origine de l'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)]

Il existe de nombreuses options pour convertir les chaînes en timbres Pandas en utilisant to_datetimealors vérifiez le docs si vous avez besoin de quelque chose de spécial.

De même, Timestamps ont beaucoup propriétés et méthodes qui peut être consulté en plus de .date


19
2017-12-20 03:03



Exemple d'objet datetime avec Django Timezone.

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)

Cette conversion est très importante pour Django et Python quand vous avez 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