[python] كيفية تحليل تاريخ تنسيق ISO 8601؟



10 Answers

ملاحظة في Python 2.6+ و Py3K ، يتم ضغط حرف٪ f microseconds.

>>> datetime.datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")

انظر القضية here

Question

أحتاج إلى تحليل سلاسل RFC 3339 مثل "2008-09-03T20:56:35.450686Z" إلى نوع datetime بيثون.

لقد وجدت strptime في مكتبة Python القياسية ، ولكنها ليست مريحة للغاية.

ما هي أفضل طريقة للقيام بذلك؟




أنا مؤلف iso8601utils. يمكن العثور عليها على github أو على PyPI . فيما يلي كيفية تحليل مثالك:

>>> from iso8601utils import parsers
>>> parsers.datetime('2008-09-03T20:56:35.450686Z')
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)

أتمنى أن يساعدك هذا!




نظرًا لأن المواصفة القياسية ISO 8601 تسمح بوجود العديد من الاختلافات في النقطتين الاختياريتين CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] ، بشكل أساسي ، CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] . إذا كنت تريد استخدام وقت التشغيل ، فستحتاج إلى إزالة هذه الأشكال أولاً.

الهدف هو إنشاء كائن وقت utc.

إذا كنت ترغب فقط في حالة أساسية تعمل مع UTC مع لاحقة Z مثل 2016-06-29T19:36:29.3453Z :

datetime.datetime.strptime(timestamp.translate(None, ':-'), "%Y%m%dT%H%M%S.%fZ")

إذا كنت تريد التعامل مع إزاحة المنطقة الزمنية مثل 2016-06-29T19:36:29.3453-0400 أو 2008-09-03T20:56:35.450686+05:00 استخدم ما يلي. هذه سوف تقوم بتحويل كل الاختلافات إلى شيء بدون المحددات المتغيرة مثل 20080903T205635.450686+0500 مما يجعله أكثر تناسقًا / أسهل للتحليل.

import re
# this regex removes all colons and all 
# dashes EXCEPT for the dash indicating + or - utc offset for the timezone
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp)
datetime.datetime.strptime(conformed_timestamp, "%Y%m%dT%H%M%S.%f%z" )

إذا كان نظامك لا يدعم توجيه %z str strime (ترى شيئًا مثل ValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z' ) فأنت بحاجة إلى يدوياً تعويض الوقت من Z (UTC). ملاحظة: قد لا يعمل %z على النظام الخاص بك في إصدارات python <3 حيث أنه يعتمد على دعم مكتبة c والذي يختلف عبر نوع بناء النظام / python (مثل Jython و Cython ، إلخ).

import re
import datetime

# this regex removes all colons and all 
# dashes EXCEPT for the dash indicating + or - utc offset for the timezone
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp)

# split on the offset to remove it. use a capture group to keep the delimiter
split_timestamp = re.split(r"[+|-]",conformed_timestamp)
main_timestamp = split_timestamp[0]
if len(split_timestamp) == 3:
    sign = split_timestamp[1]
    offset = split_timestamp[2]
else:
    sign = None
    offset = None

# generate the datetime object without the offset at UTC time
output_datetime = datetime.datetime.strptime(main_timestamp +"Z", "%Y%m%dT%H%M%S.%fZ" )
if offset:
    # create timedelta based on offset
    offset_delta = datetime.timedelta(hours=int(sign+offset[:-2]), minutes=int(sign+offset[-2:]))
    # offset datetime with timedelta
    output_datetime = output_datetime + offset_delta



تدعم الدالة parse_datetime () ل Django التواريخ التي تحتوي على إزاحات UTC:

parse_datetime('2016-08-09T15:12:03.65478Z') =
datetime.datetime(2016, 8, 9, 15, 12, 3, 654780, tzinfo=<UTC>)

لذلك يمكن استخدامه في تحليل التواريخ iso-8601 في الحقول داخل المشروع بأكمله:

from django.utils import formats
from django.forms.fields import DateTimeField
from django.utils.dateparse import parse_datetime


class DateTimeFieldFixed(DateTimeField):
def strptime(self, value, format):
    if format == 'iso-8601':
    return parse_datetime(value)
    return super().strptime(value, format)

DateTimeField.strptime = DateTimeFieldFixed.strptime
formats.ISO_INPUT_FORMATS['DATETIME_INPUT_FORMATS'].insert(0, 'iso-8601')



لقد وجدت ciso8601 ليكون أسرع طريقة ciso8601 الطوابع الزمنية ISO 8601. كما يوحي الاسم ، يتم تنفيذه في C.

import ciso8601
ciso8601.parse_datetime('2014-01-09T21:48:00.921000+05:30')

يعرض GitHub Repo README سرعة تساوي 10x> مقابل جميع المكتبات الأخرى المدرجة في الإجابات الأخرى.

شمل مشروعي الشخصي الكثير من تحليل ISO 8601. كان من الجميل أن تكون قادراً على تبديل المكالمة والذهاب بسرعة أكبر من 10 مرات. :)




يعمل هذا لـ stdlib على Python 3.2 فصاعدًا (تحرير: بفرض أن كافة الطوابع الزمنية هي UTC):

from datetime import datetime, timezone, timedelta
datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%fZ").replace(
    tzinfo=timezone(timedelta(0)))

على سبيل المثال

>>> datetime.utcnow().replace(tzinfo=timezone(timedelta(0)))
... datetime.datetime(2015, 3, 11, 6, 2, 47, 879129, tzinfo=datetime.timezone.utc)



لشيء يعمل مع مكتبة معيار 2.X حاول:

calendar.timegm(time.strptime(date.split(".")[0]+"UTC", "%Y-%m-%dT%H:%M:%S%Z"))

calendar.timegm هو نسخة gm المفقودة من time.mktime.




إذا كنت لا ترغب في استخدام dateutil ، فيمكنك تجربة هذه الوظيفة:

def from_utc(utcTime,fmt="%Y-%m-%dT%H:%M:%S.%fZ"):
    """
    Convert UTC time string to time.struct_time
    """
    # change datetime.datetime to time, return time.struct_time type
    return datetime.datetime.strptime(utcTime, fmt)

اختبار:

from_utc("2007-03-04T21:08:12.123Z")

نتيجة:

datetime.datetime(2007, 3, 4, 21, 8, 12, 123000)



ما هو الخطأ الدقيق الذي تحصل عليه؟ هل هو مثل ما يلي:

>>> datetime.datetime.strptime("2008-08-12T12:20:30.656234Z", "%Y-%m-%dT%H:%M:%S.Z")
ValueError: time data did not match format:  data=2008-08-12T12:20:30.656234Z  fmt=%Y-%m-%dT%H:%M:%S.Z

إذا كانت الإجابة بنعم ، فيمكنك تقسيم سلسلة الإدخال على "." ، ثم إضافة الميكروثانية إلى التاريخ والوقت الذي حصلت عليه.

جرب هذا:

>>> def gt(dt_str):
        dt, _, us= dt_str.partition(".")
        dt= datetime.datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S")
        us= int(us.rstrip("Z"), 10)
        return dt + datetime.timedelta(microseconds=us)

>>> gt("2008-08-12T12:20:30.656234Z")
datetime.datetime(2008, 8, 12, 12, 20, 30, 656234)
>>> 



إذا كنت تعمل مع Django ، فإنه يوفر وحدة dateparse التي تقبل مجموعة من التنسيقات المشابهة لشكل ISO ، بما في ذلك المنطقة الزمنية.

إذا كنت لا تستخدم Django ولا تريد استخدام إحدى المكتبات الأخرى المذكورة هنا ، فبإمكانك على الأرجح تعديل شفرة مصدر Django لـ dateparse إلى مشروعك.




جرب وحدة iso8601 ؛ يفعل هذا بالضبط.

هناك العديد من الخيارات الأخرى المذكورة على صفحة WorkingWithTime على موقع python.org wiki.




Related