Comment dois-je analyser un ISO 8601-date formatée?
J'ai besoin d'analyser RFC 3339 des chaînes de caractères comme "2008-09-03T20:56:35.450686Z"
en Python datetime
type.
J'ai trouvé strptime
dans le Python de la bibliothèque standard, mais il n'est pas très pratique.
Quelle est la meilleure façon de le faire?
- Python bug: issue15873: datetime: ajout de la capacité à analyser la RFC 3339 dates et horaires
- connexes: Convertir les horodatages avec un décalage de type datetime obj à l'aide de strptime
- Pour être clair: ISO 8601 est le principal standard. RFC 3339 est un auto-proclamé “profil” de la norme ISO 8601 qui fait partie du imprudent remplace de la norme ISO 8601 règles.
- Ne manquez pas les python3.7+ solution ci-dessous pour inverser isoformat()
- Cette question ne devrait pas être fermée, dans la dupe à la poste. Puisque celui-ci demande à parse ISO 8601 chaîne de temps (ce qui n'est pas pris en charge nativement par python avant de 3.7) et l'autre est de format un objet datetime dans une époque de chaîne à l'aide d'une méthode obsolète.
Vous devez vous connecter pour publier un commentaire.
La python-dateutil paquet peut analyser non seulement la RFC 3339 datetime chaînes comme celui de la question, mais aussi d'autres ISO 8601 date et l'heure des chaînes qui ne sont pas conformes à la RFC 3339 (telles que celles qui ont pas de décalage UTC, ou ceux qui ne représentent qu'une date).
Être averti que la
dateutil.parser
est intentionnellement hacky: il essaie de deviner le format et rend inévitable hypothèses (personnalisable à la main seulement) dans le cas ambigu. Donc à n'utiliser que si vous avez besoin d'analyser d'entrée de format inconnu et sont d'accord pour tolérer occasionnel interprète mal. (merci ivan_pozdeev)La Pypi nom est
python-dateutil
, pasdateutil
(merci code3monk3y):Si vous utilisez Python 3.7, jetez un oeil à cette réponse sur
datetime.datetime.fromisoformat
.python-dateutil
pasdateutil
, donc:pip install python-dateutil
.dateutil.parser
est intentionnellement hacky: il essaie de deviner le format et rend inévitable hypothèses (personnalisable à la main seulement) dans le cas ambigu. Donc à n'utiliser que si vous avez besoin d'analyser d'entrée de format inconnu et sont d'accord pour tolérer occasionnel interprète mal.iso8601
pasrfc3339
. Bien que la question est un peu déroutant, semble considérer à la fois comme le même. Je pensais que nous étions parle seulement de larfc3339
a profile of the ISO 8601
signifiea strict subset of ISO 8601
(je ne suis pas un locuteur natif). BTW, il semble y avoir un mineur incompatibilité entre les deux avec le TZ-00:00
, mais je ne pense pas que peut causer aucun problème dans mon cas.tzlocal
fuseau horaire, indépendamment deZ
apparaissant à la fin de la chaîne de temps, sur les systèmes qui sont configurés pour utiliser l'UTC comme leur fuseau horaire par défaut. Les sorties numériques produire untzoffset
tzinfo objet.from dateutil.parser import parse as parsedate
et ensuite utiliserparsedate()
au lieu dedateutil.parser.parse()
Note dans la version 2.6 de Python+ et Py3K, le %f caractère captures microsecondes.
Voir le numéro ici
strptime
est en fait impossible.datetime.datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f')
donc cela a fait le tourPlusieurs réponses ici suggérer à l'aide de
datetime.datetime.strptime
pour analyser la RFC 3339 ou ISO 8601 datetimes avec les fuseaux horaires, à l'instar de celle qui a été exposée dans la question:C'est une mauvaise idée.
En supposant que vous souhaitez en charge la totalité de la RFC 3339 format, y compris le soutien pour les décalages horaires autres que zéro, alors le code de ces réponses suggèrent ne fonctionne pas. En effet, il ne peut pas de travail, car l'analyse de la RFC 3339 de la syntaxe à l'aide de
strptime
est impossible. Les chaînes de format utilisé par Python module datetime sont incapables de décrire la RFC 3339 syntaxe.Le problème est décalages horaires. Le RFC 3339 Internet Format de Date/Heure exige que chaque date-time inclut un décalage UTC, et que ces décalages peuvent être
Z
(abréviation de "Zulu") ou dans+HH:MM
ou-HH:MM
format, comme+05:00
ou-10:30
.Par conséquent, ce sont toutes valides RFC 3339 datetimes:
2008-09-03T20:56:35.450686Z
2008-09-03T20:56:35.450686+05:00
2008-09-03T20:56:35.450686-10:30
Hélas, les chaînes de format utilisé par
strptime
etstrftime
ont pas de directive qui correspond à décalages horaires dans la RFC 3339 format. Une liste complète des directives qu'ils soutiennent peut être trouvé à https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior, et le seul décalage UTC directive inclus dans la liste est%z
:Cela ne correspond pas au format de la RFC 3339 décalage, et en effet, si nous essayons de l'utiliser
%z
dans la chaîne de format et d'analyser un RFC 3339 date, nous allons échouer:(En fait, le ci-dessus est exactement ce que vous allez voir dans Python 3. En Python 2, nous allons échouer, pour une simple raison, c'est que
strptime
ne pas mettre en œuvre le%z
de la directive à tous en Python 2.)Les multiples réponses ici que recommander
strptime
tous les travaux autour de ce en incluant un littéralZ
dans leur chaîne de format, ce qui correspond à laZ
de la question du sens de l'exemple datetime chaîne (et de rejets, de produire undatetime
objet sans fuseau horaire):Depuis cette rejets informations sur le fuseau horaire qui a été inclus dans l'original datetime chaîne, on peut se demander s'il faut considérer les même ce résultat correct. Mais plus important encore, parce que cette approche implique de codage en dur un particulier décalage UTC dans la chaîne de format, il va s'étouffer le moment, il essaie d'analyser toute la RFC 3339 datetime avec un autre décalage UTC:
Sauf si vous êtes certains que vous avez seulement besoin de prendre en charge les RFC 3339 datetimes en Zoulou temps, et pas avec d'autres décalage horaire, ne pas utiliser de
strptime
. Utilisez l'un des nombreux autres approches décrites dans les réponses ici.%z
, je viens de lancer ma chaîne à traverss = s[:-3] + s[-2:]
premier à enlever le côlon.strptime()
en Python 3.7 prend désormais en charge tout ce qui est décrit comme impossible dans cette réponse, ('Z' et littérale": "dans le décalage horaire). Malheureusement, il y a un autre coin de cas que fait la RFC 3339 fondamentalement incompatible avec la norme ISO 8601, à savoir, la première permet un négatif null décalage horaire -00:00 et le plus tard pas.Nouveau en Python de 3,7+
La
datetime
de la bibliothèque standard introduit une fonction pour inverserdatetime.isoformat()
.Exemple d'utilisation:
datetime
peut contenir untzinfo
, et donc la sortie d'un fuseau horaire, maisdatetime.fromisoformat()
ne pas analyser les tzinfo ? semble comme un bug ..isoformat
. Il n'accepte pas l'exemple dans la question"2008-09-03T20:56:35.450686Z"
en raison de la fuiteZ
, mais il n'accepte"2008-09-03T20:56:35.450686"
.Z
le script d'entrée peut être modifié avecdate_string.replace("Z", "+00:00")
.Essayer le iso8601 module; il fait exactement cela.
Il y a plusieurs autres options mentionnées sur le WorkingWithTime page sur le python.org wiki.
iso8601.parse_date("2008-09-03T20:56:35.450686Z")
datetime.datetime(*map(int, re.findall('\d+', s))
Quelle est l'erreur exacte que vous obtenez? Est-ce comme le suivant?
Si oui, vous pouvez diviser votre chaîne d'entrée sur ".", puis ajouter quelques microsecondes à la date que vous avez obtenu.
Essayez ceci:
""
ou"Z"
, alors il doit y avoir un décalage dans les heures/minutes, ce qui peut être directement ajouté à/soustrait de l'objet datetime. vous pourrait créer un tzinfo sous-classe de gérer ça, mais ce n'est probablement pas recommandé.À partir de Python 3.7, strptime prend en charge côlon délimiteurs dans les décalages horaires (source). De sorte que vous pouvez ensuite utiliser:
datetime.fromisoformat()
qui manipule des chaînes de caractères comme votre entrée automatiquement:datetime.datetime.isoformat('2018-01-31T09:24:31.488670+00:00')
.datetime.fromisoformat()
etdatetime.isoformat()
Dans ces jours, Flèche peut également être utilisé comme une solution tierce:
Si vous ne souhaitez pas utiliser dateutil, vous pouvez essayer cette fonction:
Test:
Résultat:
strptime
. C'est une mauvaise idée, car il ne parvient pas à analyser n'importe quel type datetime avec un autre décalage UTC et lever une exception. Voir ma réponse qui explique comment l'analyse RFC 3339 avec strptime est en fait impossible.toISOString
de la méthode. Mais il n'y a aucune mention de la limitation de la Zulu dates dans cette réponse, ni la question n'indiquent que c'est tout ce qui est nécessaire, et seulement à l'aide dedateutil
est généralement tout aussi pratique et moins étroit dans ce qu'il peut analyser.Suffit d'utiliser la
python-dateutil
module:La Documentation
455051100
(vérifié dans le epochconverter.com),,, à moins que je me manque quelque chose?datetime.datetime.timestamp()
est sans doute une meilleure solution.sprintf("%s")
. Code qui ne fonctionne pas partout, pour tout le monde est, par définition, buggy.Si vous travaillez avec Django, il fournit la dateparse module qui accepte un tas de formats similaires aux format ISO, y compris le fuseau horaire.
Si vous n'êtes pas à l'aide de Django et vous ne voulez pas utiliser l'un des autres bibliothèques mentionnés ici, vous pouvez probablement s'adapter le Django code source pour dateparse à votre projet.
DateTimeField
l'utilise lorsque vous définissez une valeur de chaîne.J'ai trouvé ciso8601 être le moyen le plus rapide pour analyser la norme ISO 8601 horodateurs. Comme son nom l'indique, il est mis en œuvre dans C.
La Dépôt GitHub README montre leur >10x plus rapide par rapport à tous les autres bibliothèques répertoriées dans les autres réponses.
Mon projet personnel impliqué un grand nombre de la norme ISO 8601 l'analyse. C'était agréable d'être en mesure de passer l'appel et 10x plus rapide. 🙂
Edit: depuis j'ai pris un responsable de ciso8601. Il est maintenant plus rapide que jamais!
datetime.strptime()
est la prochaine solution la plus rapide. Merci de mettre toutes ces infos ensemble!datetime.strptime()
n'est pas un plein format ISO 8601 l'analyse de la bibliothèque. Si vous êtes sur Python 3.7, vous pouvez utiliser ledatetime.fromisoformat()
méthode, qui est un peu plus souple. Vous pourriez être intéressé dans cette liste plus complète d'analyseurs qui devraient être intégrés dans le ciso8601 README bientôt.Je suis l'auteur de iso8601 utils. Il peut être trouvé sur GitHub ou sur PyPI. Voici comment vous pouvez analyser votre exemple:
Un moyen simple de convertir une ISO 8601-comme la chaîne de date pour un timestamp UNIX ou
datetime.datetime
objet dans tous pris en charge les versions de Python sans l'installation de modules tiers est d'utiliser le date de l'analyseur de SQLite.De sortie:
J'ai codé un analyseur syntaxique pour la norme ISO 8601, et le mettre sur GitHub: https://github.com/boxed/iso8601. Cette application prend en charge tout dans la norme, sauf pour la durée, les intervalles, intervalles périodiques, et des dates en dehors de la pris en charge plage de dates de Python module datetime.
Tests sont inclus! 😛
Cela fonctionne pour stdlib sur Python 3.2 à partir de (en supposant que tous les horodateurs sont en UTC):
Par exemple,
strptime
. C'est une mauvaise idée, car il ne parvient pas à analyser n'importe quel type datetime avec un autre décalage UTC et lever une exception. Voir ma réponse qui explique comment l'analyse RFC 3339 avec strptime est en fait impossible.timezone.utc
au lieu detimezone(timedelta(0))
. Aussi, le code fonctionne en Python 2.6+ (au moins) si vous l'offreutc
tzinfo objet%Z
de fuseau horaire dans les plus récentes versions de Python.De Django reinhardt, parse_datetime() supporte les dates avec les décalages horaires:
De sorte qu'il pourrait être utilisé pour l'analyse de la norme ISO 8601 dates dans les champs à l'intérieur de tout le projet:
Parce que la norme ISO 8601 permet de nombreuses variations de l'option des deux points et des tirets être présent, essentiellement
CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
. Si vous souhaitez utiliser strptime, vous devez enlever les variations d'abord.L'objectif est de générer un utc objet datetime.
Si vous voulez juste une base de cas que le travail de l'UTC avec le Z de suffixe comme
2016-06-29T19:36:29.3453Z
:Si vous souhaitez gérer le décalage horaire comme
2016-06-29T19:36:29.3453-0400
ou2008-09-03T20:56:35.450686+05:00
utilisation suivantes. Ces convertira toutes les variations dans quelque chose sans variable délimiteurs comme20080903T205635.450686+0500
en la rendant plus cohérente/plus facile à analyser.Si votre système ne prend pas en charge la
%z
strptime directive (vous voyez quelque chose commeValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z'
), alors vous avez besoin de décaler manuellement le temps deZ
(UTC). Note%z
peut ne pas fonctionner sur votre système dans les versions de python < 3 car cela dépend de la bibliothèque c de soutien qui varie à l'échelle du système/python type de build (c'est à dire Jython, Cython, etc.).Pour quelque chose qui fonctionne avec les 2.X de la bibliothèque standard essayer:
calendrier.timegm est l'absence de version gm de temps.mktime.
Python-dateutil va lever une exception si l'analyse invalide date de chaînes, de sorte que vous pouvez intercepter l'exception.
Aujourd'hui, il ya Maya: Datetimes pour les Humains™, de l'auteur de la populaire Demandes: HTTP pour les Humains™ package:
Grâce à la grande Marque Amery réponse j'ai trouvé la fonction pour tenir compte de tous les possibles ISO formats de date /heure:
Note que nous devrions rechercher si la chaîne n'a pas finit avec
Z
, nous avons pu analyser à l'aide de%z
.Au départ, j'ai essayé avec:
Mais cela ne fonctionne pas sur les fuseaux horaires. Ceci, cependant, j'ai eu à travailler, en Python 3.7.3:
Quelques tests, notez que le ne diffèrent que par la précision de quelques microsecondes. Arrivés à 6 chiffres de précision sur ma machine, mais YMMV:
frozenset(('+', '-'))
? Ne faut-il pas normal tuple comme('+', '-')
être en mesure de faire la même chose?