मैं आईएसओ 8601-स्वरूपित तारीख को पार्स कैसे कर सकता हूं?


642

मुझे पायथन के प्रकार की तरह RFC 3339 स्ट्रिंग्स को पार्स करने की आवश्यकता है ।"2008-09-03T20:56:35.450686Z"datetime

मैंने strptimeपायथन मानक पुस्तकालय में पाया है, लेकिन यह बहुत सुविधाजनक नहीं है।

इसे करने का बेहतरीन तरीका क्या है?


6
पायथन बग: अंक 15873
jfs


3
स्पष्ट होने के लिए: आईएसओ 8601 मुख्य मानक है। RFC 3339 ISO 8601 का एक स्व-घोषित "प्रोफाइल" है जो आईएसओ 8601 नियमों के कुछ नासमझ ओवरराइड करता है।
बेसिल बोर्क

3
Isoformat ()
ब्रैड एम

2
इस प्रश्न को लिंक किए गए पोस्ट के रूप में बंद नहीं किया जाना चाहिए। चूँकि यह एक आईएसओ 8601 टाइम स्ट्रिंग (जो कि मूल रूप से 3.7 से पहले अजगर द्वारा समर्थित नहीं था) को पार्स करने के लिए कह रहा है और दूसरा एक अप्रचलित विधि का उपयोग करके एक युगांतर स्ट्रिंग में एक डेटाइम ऑब्जेक्ट को प्रारूपित करने के लिए है।
abccd

जवाबों:


462

अजगर-dateutil पैकेज प्रश्न में से एक की तरह न केवल आरएफसी 3339 दिनांक तार पार्स कर सकते हैं, लेकिन यह भी अन्य आईएसओ 8601 कोई यूटीसी के साथ लोगों को ऑफसेट (जैसे दिनांक और समय तार कि आरएफसी 3339 का अनुपालन नहीं करते या ऐसे प्रतिनिधित्व करते हैं केवल एक तारीख)।

>>> import dateutil.parser
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686Z') # RFC 3339 format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686') # ISO 8601 extended format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903T205635.450686') # ISO 8601 basic format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903') # ISO 8601 basic format, date only
datetime.datetime(2008, 9, 3, 0, 0)

ध्यान दें कि dateutil.parser.isoparseसंभवतः अधिक हैकी की तुलना में सख्त है dateutil.parser.parse, लेकिन वे दोनों काफी क्षमाशील हैं और उस स्ट्रिंग की व्याख्या करने का प्रयास करेंगे जो आप पास करते हैं। यदि आप किसी भी गलतफहमी की संभावना को खत्म करना चाहते हैं, तो आपको इन दोनों में से कुछ का उपयोग करने की आवश्यकता है। कार्य करता है।

Pypi नाम है python-dateutil, नहीं dateutil(धन्यवाद code3monk3y ):

pip install python-dateutil

यदि आप Python 3.7 का उपयोग कर रहे हैं, तो इस उत्तर के बारे में एक नज़र डालें datetime.datetime.fromisoformat


75
आलसी के लिए, यह के माध्यम से स्थापित किया गया है python-dateutilनहीं dateutilहै, तो: pip install python-dateutil
cod3monk3y

29
सावधान रहें कि dateutil.parserजानबूझकर हैक किया गया है: यह प्रारूपण का अनुमान लगाने की कोशिश करता है और अस्पष्ट मामलों में अपरिहार्य धारणाएं (केवल हाथ से अनुकूलन) बनाता है। तो केवल इसका उपयोग करें यदि आपको अज्ञात प्रारूप के इनपुट को पार्स करने की आवश्यकता है और कभी-कभार होने वाली गड़बड़ियों को सहन करने के लिए ठीक है।
ivan_pozdeev

2
माना। एक उदाहरण 9999 की "तारीख" से गुजर रहा है। यह डेटटाइम (9999, वर्तमान माह, वर्तमान दिन) के रूप में वापस आ जाएगा। मेरे विचार में वैध तिथि नहीं है।
टिम्बो

1
@ivan_pozdeev गैर-अनुमानित पार्सिंग के लिए आप किस पैकेज की सिफारिश करेंगे?
bgusach 12

2
@ivan_pozdeev iso8601 तिथियों को पढ़ने वाले मॉड्यूल के लिए एक अद्यतन है: dateutil.readthedocs.io/en/stable/…
एप्सिलॉन

196

पायथन 3.7+ में नया


datetimeमानक पुस्तकालय inverting के लिए एक समारोह की शुरुआत की datetime.isoformat()

classmethod datetime.fromisoformat(date_string):

इसके द्वारा उत्सर्जित स्वरूपों में datetimeसे एक date_stringमें एक के लिए एक वापसी date.isoformat()और datetime.isoformat()

विशेष रूप से, यह फ़ंक्शन प्रारूप में तार का समर्थन करता है:

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

जहाँ *किसी भी एक पात्र का मिलान किया जा सकता है।

सावधानी : यह आईएसओ 8601 स्ट्रिंग्स के मनमाने ढंग से समर्थन नहीं करता है - यह केवल उलटा ऑपरेशन के रूप में करना है datetime.isoformat()

उपयोग का उदाहरण:

from datetime import datetime

date = datetime.fromisoformat('2017-01-01T12:30:59.000000')

6
वह अजीब है। क्योंकि datetimeइसमें एक शामिल हो सकता है tzinfo, और इस तरह एक datetime.fromisoformat()टाइमज़ोन आउटपुट हो सकता है , लेकिन tzinfo को पार्स नहीं करता है? एक बग की तरह लगता है ..
Hendy Irawan

20
प्रलेखन में उस नोट को याद न करें, यह सभी मान्य आईएसओ 8601 स्ट्रिंग्स को स्वीकार नहीं करता है , केवल लोगों द्वारा उत्पन्न किया जाता है isoformat। यह अनुगमन के "2008-09-03T20:56:35.450686Z"कारण प्रश्न में उदाहरण को स्वीकार नहीं करता है Z, लेकिन यह स्वीकार करता है "2008-09-03T20:56:35.450686"
फ़्लिम

26
Zइनपुट स्क्रिप्ट का ठीक से समर्थन करने के लिए इसके साथ संशोधित किया जा सकता है date_string.replace("Z", "+00:00")
jox

7
ध्यान दें कि सेकंड के लिए यह केवल 0, 3 या 6 दशमलव स्थानों को ही संभालता है। यदि इनपुट डेटा में 1, 2, 4, 5, 7 या अधिक दशमलव स्थान हैं, तो पार्सिंग विफल हो जाएगी!
फेलक

1
@JDOaktown इस उदाहरण में देशी पायथन के डेटाइम लाइब्रेरी का उपयोग किया गया है, न कि खजूर के पार्सर का। यह वास्तव में विफल हो जाएगा अगर दशमलव स्थान इस दृष्टिकोण के साथ 0, 3, या 6 नहीं हैं।
abccd

174

पायथन 2.6+ और Py3K में नोट,% f वर्ण माइक्रोसेकंड पकड़ता है।

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

यहां देखें मुद्दा


4
नोट - यदि Naive datetimes का उपयोग किया जाता है - मुझे लगता है कि आपको कोई भी TZ नहीं मिला है - Z कुछ भी मेल नहीं खा सकता है।
डैनी स्टैपल

24
यह उत्तर (इसके वर्तमान, संपादित रूप में) एक विशेष UTC ऑफसेट (जैसे कि "Z", जिसका अर्थ है +00: 00) हार्ड-कोडिंग पर निर्भर करता है, प्रारूप स्ट्रिंग में। यह एक बुरा विचार है क्योंकि यह किसी भी UTC ऑफसेट के साथ किसी भी डेटाटाइम को पार्स करने और किसी अपवाद को उठाने में विफल रहेगा। मेरा उत्तर देखें जो बताता है कि RFC 3339 के साथ पार्स strptimeकरना वास्तव में कितना असंभव है।
मार्क अमेरी

1
मेरे मामले में% f ने Z के बजाय microseconds को पकड़ा, datetime.datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f') इसलिए इसने यह चाल
चली

क्या Py3K का अर्थ Python 3000 है?!?
रोबिनो

2
@ रबिनो IIRC, "पायथन 3000" एक पुराना नाम है जिसे अब पायथन 3 के रूप में जाना जाता है
थ्रो अवे अकाउंट

161

यहाँ कई उत्तर आरएफसी 3339 या आईएसओ 8601 डेटासेटाइम को पार्स करने के लिए उपयोग करने का सुझाव देते हैं , जैसे प्रश्न में प्रदर्शित किया गया है: datetime.datetime.strptime

2008-09-03T20:56:35.450686Z

यह विचार अच्छा नहीं है।

यह मानते हुए कि आप पूर्ण RFC 3339 प्रारूप का समर्थन करना चाहते हैं, जिसमें शून्य के अलावा UTC ऑफसेट के लिए समर्थन शामिल है, तो इन उत्तरों का सुझाव देने वाला कोड काम नहीं करता है। वास्तव में, यह काम नहीं कर सकता , क्योंकि RFC 3339 सिंटैक्स का उपयोग strptimeकरना असंभव है। पायथन के डेटाइम मॉड्यूल द्वारा उपयोग किए गए प्रारूप के तार RFC 3339 सिंटैक्स का वर्णन करने में असमर्थ हैं।

समस्या यूटीसी ऑफसेट है। आरएफसी 3339 इंटरनेट दिनांक / समय स्वरूप हर तिथि-समय एक यूटीसी ऑफसेट शामिल है, और है कि उन ऑफसेट या तो हो सकता है कि आवश्यकता है Z(छोटी "ज़ुलु समय" के लिए) या में +HH:MMया -HH:MMप्रारूप, जैसे +05:00या -10:30

नतीजतन, ये सभी वैध RFC 3339 डेटासेट हैं:

  • 2008-09-03T20:56:35.450686Z
  • 2008-09-03T20:56:35.450686+05:00
  • 2008-09-03T20:56:35.450686-10:30

का उपयोग, प्रारूप स्ट्रिंग द्वारा उपयोग किया जाता है strptimeऔर strftimeकोई निर्देश नहीं है जो RFC 3339 प्रारूप में UTC ऑफसेट से मेल खाता है। उनके द्वारा समर्थित निर्देशों की एक पूरी सूची https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior पर देखी जा सकती है , और सूची में शामिल केवल UTC ऑफसेट निर्देश है %z:

% z

UTC फॉर्म + HHMM या -HHMM (यदि वस्तु भोली है तो रिक्त स्ट्रिंग) में ऑफसेट।

उदाहरण: (खाली), +0000, -0400, +1030

यह RFC 3339 ऑफसेट के प्रारूप से मेल नहीं खाता है, और वास्तव में अगर हम %zप्रारूप स्ट्रिंग में उपयोग करने का प्रयास करते हैं और RFC 3339 तारीख को पार्स करते हैं, तो हम असफल होंगे:

>>> from datetime import datetime
>>> datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%f%z")
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
    (data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686Z' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
>>> datetime.strptime("2008-09-03T20:56:35.450686+05:00", "%Y-%m-%dT%H:%M:%S.%f%z")
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
    (data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686+05:00' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'

(वास्तव में, उपरोक्त वही है जो आप पायथन 3 में देखेंगे। Python 2 में हम एक और भी सरल कारण के लिए असफल होंगे, जो कि Python 2 में निर्देश को strptimeलागू नहीं करता है%z ।)

यहां कई उत्तर हैं जो इसके प्रारूप स्ट्रिंग में strptimeशाब्दिक रूप से शामिल करके इसके चारों ओर काम करने की सलाह देते हैं Z, जो Zप्रश्न पूछने वाले के उदाहरण डेटाइम स्ट्रिंग से मेल खाता है (और इसे अनसुना कर देता है, datetimeबिना टाइमज़ोन के किसी वस्तु का उत्पादन )

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

चूंकि यह टाइमज़ोन की जानकारी को मूल डेटाइम स्ट्रिंग में शामिल करता है, इसलिए यह संदेहास्पद है कि क्या हमें इस परिणाम को सही मानना ​​चाहिए। लेकिन इससे भी महत्वपूर्ण बात, क्योंकि इस दृष्टिकोण में एक विशेष UTC ऑफसेट को हार्ड-कोडिंग के साथ प्रारूप स्ट्रिंग में शामिल किया गया है , यह किसी भी RFC 3339 डेटाटाइम को एक अलग UTC ऑफसेट के साथ पार्स करने की कोशिश करने वाले पल को चोक करेगा:

>>> datetime.strptime("2008-09-03T20:56:35.450686+05:00", "%Y-%m-%dT%H:%M:%S.%fZ")
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
    (data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686+05:00' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'

जब तक आप निश्चित नहीं हैं कि आपको केवल ज़ुलु समय में RFC 3339 डेटासेट का समर्थन करने की आवश्यकता है, और अन्य टाइमज़ोन ऑफ़सेट वाले लोगों का उपयोग नहीं करते हैं strptime। इसके बजाय उत्तर में वर्णित कई अन्य दृष्टिकोणों में से एक का उपयोग करें।


79
यह दिमाग चकरा रहा है कि स्ट्रैपीम में आईएसओ प्रारूप टाइमज़ोन जानकारी के लिए कोई निर्देश नहीं है, और इसे पार्स क्यों नहीं किया जा सकता है। अतुल्य।
सेबा ताथ

2
@CabaToth पूरी तरह से सहमत है - अगर मेरे पास मारने के लिए कुछ समय है, तो शायद मैं इसे भाषा में जोड़ने की कोशिश करूंगा। या आप ऐसा कर सकते हैं, यदि आप इतने इच्छुक थे - मुझे लगता है कि आपको मेरे विपरीत कुछ सी अनुभव है।
मार्क अमेरी

1
@CabaToth - अविश्वसनीय क्यों? यह ज्यादातर लोगों के लिए काफी अच्छा काम करता है, या उन्हें आसानी से पर्याप्त समाधान मिल गया है। यदि आपको सुविधा की आवश्यकता है, तो यह ओपनसोर्स है और आप इसे जोड़ सकते हैं। या किसी को इसके लिए भुगतान करें। किसी को अपनी विशिष्ट समस्याओं को हल करने के लिए अपना स्वयं का खाली समय क्यों देना चाहिए? स्रोत को अपने साथ रहने दो।
पीटर एम। -

2
@PeterMasiar अतुल्य क्योंकि आमतौर पर एक पता चलता है कि अजगर में चीजों को सोच-समझकर और पूरी तरह से लागू किया गया है। हम इस ध्यान को विस्तार से खराब कर चुके हैं और इसलिए जब हम "अनहाइथोनिक" भाषा में किसी चीज़ पर ठोकर खाते हैं, तो हम अपने खिलौनों को प्रैम से बाहर फेंक देते हैं, जैसा कि मैं अभी करने वाला हूं। वहाआ वाया वहा वहाआ :-(
रोबिनो नोव

2
strptime()पायथॉन 3.7 में अब इस उत्तर में असंभव ('जेड' शाब्दिक और ':' समय-सीमा में ऑफसेट) के रूप में वर्णित सब कुछ का समर्थन करता है। दुर्भाग्य से, एक और कोने का मामला है जो RFC 3339 को मूल रूप से आईएसओ 8601 के साथ असंगत बनाता है, अर्थात्, पूर्व एक नकारात्मक अशक्त timezone ऑफ़सेट -00: 00 और बाद में नहीं की अनुमति देता है।
SergiyKolesnikov

75

Iso8601 मॉड्यूल की कोशिश करो ; यह ठीक यही करता है।

Python.org विकी पर वर्कविथ टाइम पेज पर कई अन्य विकल्पों का उल्लेख किया गया है ।


सरल के रूप मेंiso8601.parse_date("2008-09-03T20:56:35.450686Z")
पाकमन

3
सवाल यह नहीं था कि "मैं आईएसओ 8601 तारीखों को कैसे पार्स करता हूं", यह था "मैं इस सटीक तिथि प्रारूप को कैसे पार्स करता हूं।"
निकोलस रिले

3
@tiktak ओपी ने पूछा कि "मुझे एक्स की तरह स्ट्रिंग्स को पार्स करने की आवश्यकता है" और मेरा जवाब, दोनों पुस्तकालयों की कोशिश करने के बाद, एक दूसरे का उपयोग करना है, क्योंकि iso8601 में अभी भी महत्वपूर्ण मुद्दे खुले हैं। इस तरह की परियोजना में मेरी भागीदारी या उसकी कमी पूरी तरह से उत्तर से संबंधित नहीं है।
टोबिया

2
ध्यान रखें कि 2007 से iso8601 के पाइप संस्करण को अपडेट नहीं किया गया है और इसमें कुछ गंभीर कीड़े हैं जो बकाया हैं। मैं खुद पैच के कुछ महत्वपूर्ण को लागू करने की सलाह देता हूं या कई
गिथब फोर्क्स में से एक ढूंढता हूं

6
iso8601 , उर्फ pyiso8601 , हाल ही में फ़रवरी 2014 के रूप में अद्यतन किया गया है। नवीनतम संस्करण आईएसओ 8601 स्ट्रिंग्स के बहुत व्यापक सेट का समर्थन करता है। मैं अपनी कुछ परियोजनाओं में अच्छे प्रभाव का उपयोग कर रहा हूं।
डेव हेन

34
आयात फिर, डेटाइम
रों = "2008-09-03T20: 56: 35.450686Z"
d = datetime.datetime (* map (int, re.split ('[^ \ d]', s) [: - 1])

73
मैं असहमत हूं, यह व्यावहारिक रूप से अपठनीय है और जहां तक ​​मैं बता सकता हूं कि ज़ुलु (जेड) को ध्यान में नहीं रखा गया है जो इस डेटाटाइम को भोले बनाता है भले ही समय क्षेत्र डेटा प्रदान किया गया था।
15

14
मुझे यह काफी पठनीय लगता है। वास्तव में, यह संभवतः अतिरिक्त पैकेजों को स्थापित किए बिना रूपांतरण करने का सबसे आसान और सबसे बेहतर तरीका है।
टोबिया

2
यह d = datetime.datetime (* map (int, re.split ('\ D', s) [: - 1]) के बराबर है) मुझे लगता है।
ज़ुआन

4
एक बदलाव:datetime.datetime(*map(int, re.findall('\d+', s))
JFS

3
यह बिना समय-सीमा के एक भोली डेटाइम वस्तु में परिणत होता है, है ना? यूटीसी बिट अनुवाद में खो जाता है?
w00t

32

सटीक त्रुटि क्या है? यह निम्नलिखित की तरह है?

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

10
आप सिर्फ पट्टी .Z नहीं कर सकते क्योंकि इसका मतलब टाइमजोन है और अलग हो सकता है। मुझे UTC के समयक्षेत्र में तारीख बदलने की आवश्यकता है।
अलेक्जेंडर आर्टेमेंको

एक सादे डेटाटाइम ऑब्जेक्ट में टाइमज़ोन की कोई अवधारणा नहीं है। यदि आपका सारा समय "Z" में समाप्त हो रहा है, तो आपके द्वारा प्राप्त सभी डेटासेट UTC (ज़ुलु समय) हैं।
16

अगर समय क्षेत्र के अलावा और कुछ है ""या "Z"है, तो यह घंटे / मिनट, जो सीधे करने के लिए / datetime वस्तु से घटाया जोड़ा जा सकता है में एक ऑफसेट किया जाना चाहिए। आप इसे संभालने के लिए एक tzinfo उपवर्ग बना सकते हैं, लेकिन यह संभव नहीं है।
सिंगलएनजेशन इलिमिनेशन

8
इसके अतिरिक्त, "% f" माइक्रोसेकंड स्पेसियर है, इसलिए एक (टाइमजोन-भोले) स्ट्रैपीम स्ट्रिंग ऐसा दिखता है: "% Y-% m-% dT% H:% M:% S.% f"।
quodlibetor

1
यह अपवाद को बढ़ा देगा यदि दिए गए डेटाइम स्ट्रिंग में "Z" के अलावा UTC ऑफसेट है। यह संपूर्ण RFC 3339 प्रारूप का समर्थन नहीं करता है और दूसरों के लिए एक हीन उत्तर है जो UTC ऑफसेट को ठीक से संभालता है।
मार्क अमेरी

24

पायथन 3.7 से शुरू, स्ट्रैपटाइम यूटीसी ऑफसेट्स ( स्रोत ) में कोलोन डेलिमिटर का समर्थन करता है । तो आप तब उपयोग कर सकते हैं:

import datetime
datetime.datetime.strptime('2018-01-31T09:24:31.488670+00:00', '%Y-%m-%dT%H:%M:%S.%f%z')

संपादित करें:

जैसा कि मार्टिज्न ने बताया है, अगर आपने आइसोफोर्मैट () का उपयोग करके डेटाइम ऑब्जेक्ट बनाया है, तो आप बस डेटाइम.फ्रेमिसोफॉर्म () का उपयोग कर सकते हैं


4
लेकिन 3.7 में, आप भी पास है datetime.fromisoformat()जो आपके इनपुट की तरह तार को स्वचालित रूप से संभालता है datetime.datetime.isoformat('2018-01-31T09:24:31.488670+00:00'):।
मार्टिन पीटर्स

2
अच्छी बात। मैं सहमत हूं, मैं उपयोग करने की सलाह देता हूं datetime.fromisoformat()औरdatetime.isoformat()
एंड्रियास प्रोफस

19

इन दिनों में, तीर का उपयोग तीसरे पक्ष के समाधान के रूप में भी किया जा सकता है:

>>> import arrow
>>> date = arrow.get("2008-09-03T20:56:35.450686Z")
>>> date.datetime
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())

6
एरो ISO8601 का ठीक से समर्थन नहीं करता है: github.com/crsmithdev/arrow/issues/291
बॉक्सिंग

1
बस अजगर डेटोनिल का उपयोग करें - तीर को अजगर डेटोनिल की आवश्यकता होती है।
danizen

तीर अब ISO8601 का समर्थन करता है। संदर्भित मुद्दे अब बंद हो गए हैं।
Altus

17

बस python-dateutilमॉड्यूल का उपयोग करें :

>>> import dateutil.parser as dp
>>> t = '1984-06-02T19:05:00.000Z'
>>> parsed_t = dp.parse(t)
>>> print(parsed_t)
datetime.datetime(1984, 6, 2, 19, 5, tzinfo=tzutc())

प्रलेखन


1
क्या यह ठीक ऊपर @ उत्तर नहीं है?
लियो

1
आप उसे सेकंड में पार्स करते हुए कहाँ देखते हैं? मैंने इस लेख को युगांतरकारी समय प्राप्त करने का प्रयास करके पाया, इसलिए मुझे लगा कि कोई और भी होगा।
ब्लेयरग 2323

1
यह मेरे सिस्टम पर UTC नहीं है। बल्कि, सेकंड में आउटपुट यूनिक्स युग का समय है जैसे कि तारीख मेरे स्थानीय समय क्षेत्र में थी।
इलियट

1
यह उत्तर छोटी गाड़ी है और इसे स्वीकार नहीं किया जाना चाहिए। संभवत: पूरे प्रश्न को stackoverflow.com/questions/11743019/… के
ट्रिपल

@tripleee वास्तव में मैंने अभी कोड की जाँच की है और यह सही उत्तर देने के लिए प्रकट होता है: 455051100( epochconverter.com पर जाँच की गई ) ,,, जब तक मैं कुछ याद नहीं कर रहा हूँ?
ब्लेयरग 2323 12'18

13

यदि आप खजूर का उपयोग नहीं करना चाहते हैं, तो आप इस कार्य को आजमा सकते हैं:

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)

5
यह उत्तर एक विशेष UTC ऑफसेट (अर्थात "Z" को हार्ड-कोडिंग पर निर्भर करता है, जिसका अर्थ है +00: 00) प्रारूप स्ट्रिंग में strptime। यह एक बुरा विचार है क्योंकि यह किसी भी UTC ऑफसेट के साथ किसी भी डेटाटाइम को पार्स करने और एक अपवाद को बढ़ाने में विफल रहेगा। मेरा उत्तर देखें जो बताता है कि स्ट्रैचम के साथ RFC 3339 को पार्स करना वास्तव में असंभव है।
मार्क अमेरी

1
यह हार्ड कोडित है, लेकिन मामले के लिए पर्याप्त है जब आपको केवल ज़ुलु को पार्स करने की आवश्यकता होती है।
साशा

1
@alexander हाँ - अगर ऐसा हो सकता है, उदाहरण के लिए, आप जानते हैं कि आपकी तारीख स्ट्रिंग जावास्क्रिप्ट toISOStringविधि के साथ उत्पन्न हुई थी । लेकिन इस उत्तर में ज़ुलु समय की तारीखों तक सीमित होने का कोई उल्लेख नहीं है, और न ही प्रश्न ने संकेत दिया कि यह है कि सभी की जरूरत है, और बस का उपयोग dateutilकरना आमतौर पर उतना ही सुविधाजनक और कम संकीर्ण है जो इसे पार्स कर सकता है।
मार्क अमेरी

11

यदि आप Django के साथ काम कर रहे हैं, तो यह समय क्षेत्र सहित आईएसओ प्रारूप के समान स्वरूपों का एक गुच्छा स्वीकार करता है, जो डेटापार्स मॉड्यूल प्रदान करता है।

यदि आप Django का उपयोग नहीं कर रहे हैं और आप यहां बताए गए अन्य पुस्तकालयों में से किसी एक का उपयोग नहीं करना चाहते हैं, तो आप संभवतः अपनी परियोजना के लिए तिथि निर्धारण के लिए Django स्रोत कोड को अनुकूलित कर सकते हैं।


DateTimeFieldजब आप एक स्ट्रिंग मान सेट करते हैं तो Django का उपयोग करता है।
djvg

11

मैंने आईएसओ 8601 टाइमस्टैम्प को पार्स करने का सबसे तेज़ तरीका ciso8601 पाया है । जैसा कि नाम से पता चलता है, इसे C में लागू किया गया है।

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

GitHub रेपो README अन्य उत्तर में सूचीबद्ध अन्य पुस्तकालयों के सभी बनाम उनके> 10x speedup को दर्शाता है।

मेरी व्यक्तिगत परियोजना में आईएसओ 8601 पार्सिंग का एक बहुत कुछ शामिल था। बस कॉल स्विच करने और 10x तेज़ी से जाने में सक्षम होना अच्छा था। :)

संपादित करें: मैं तब से ciso8601 का अनुचर बन गया हूं। यह अब पहले से कहीं ज्यादा तेज है!


यह एक महान पुस्तकालय जैसा दिखता है! Google App Engine पर ISO8601 पार्सिंग का अनुकूलन करने के इच्छुक लोगों के लिए, दुख की बात है कि हम इसका उपयोग C लाइब्रेरी के बाद से नहीं कर सकते हैं, लेकिन आपके बेंचमार्क यह दिखाने के लिए व्यावहारिक थे कि मूल datetime.strptime()अगला सबसे तेज समाधान है। उस जानकारी को एक साथ रखने के लिए धन्यवाद!
हैमक्स ०r

3
@ हैम्क्स 0 आरआर, ध्यान रखें कि datetime.strptime()पूर्ण आईएसओ 8601 पार्सिंग लाइब्रेरी नहीं है। यदि आप पायथॉन 3.7 पर हैं, तो आप datetime.fromisoformat()विधि का उपयोग कर सकते हैं , जो थोड़ा अधिक लचीला है। आपको पार्सर्स की इस पूरी सूची में दिलचस्पी हो सकती है जिसे जल्द ही ciso8601 README में विलय कर दिया जाना चाहिए।
मोवरमेयर

ciso8601 काफी अच्छा काम करता है, लेकिन किसी को पहले "पिप इंस्टॉल पाइत्ज़" करना होगा, क्योंकि कोई भी पाइट निर्भरता के बिना टाइम ज़ोन की जानकारी के साथ टाइमस्टैम्प को पार्स नहीं कर सकता है। उदाहरण इस तरह दिखेगा: dob = ciso8601.parse_datetime (परिणाम ['dob'] ['तारीख'])
डिर्क

2
@ डर्क, केवल पायथन 2 में । लेकिन अगली रिलीज में भी इसे हटा दिया जाना चाहिए
मावरमेयर

8

यह पाइथन 3.2 के बाद से स्टडलिब के लिए काम करता है (सभी टाइमस्टैम्प्स यूटीसी हैं):

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
यह उत्तर एक विशेष UTC ऑफसेट (अर्थात "Z" को हार्ड-कोडिंग पर निर्भर करता है, जिसका अर्थ है +00: 00) प्रारूप स्ट्रिंग में strptime। यह एक बुरा विचार है क्योंकि यह किसी भी UTC ऑफसेट के साथ किसी भी डेटाटाइम को पार्स करने और एक अपवाद को बढ़ाने में विफल रहेगा। मेरा उत्तर देखें जो बताता है कि स्ट्रैचम के साथ RFC 3339 को पार्स करना वास्तव में असंभव है।
मार्क अमेरी

1
सिद्धांत रूप में, हाँ, यह विफल रहता है। व्यवहार में, मैंने कभी भी आईएसओ 8601-स्वरूपित तारीख का सामना नहीं किया है जो ज़ुलु समय में नहीं था। मेरी कभी-कभार की जरूरत के लिए, यह बहुत अच्छा काम करता है और कुछ बाहरी लाइब्रेरी पर निर्भर नहीं करता है।
बेंजामिन रिग्स

4
आप timezone.utcइसके बजाय उपयोग कर सकते हैं timezone(timedelta(0))। इसके अलावा, यदि आप tzinfo ऑब्जेक्ट सप्लाईutc
jfs

इससे कोई फर्क नहीं पड़ता कि आपने इसका सामना किया है, यह कल्पना से मेल नहीं खाता।
थिअन्नूनर

आप %Zपायथन के सबसे हाल के संस्करणों में टाइमज़ोन के लिए उपयोग कर सकते हैं ।
18 नवंबर को

7

मैं iso8601 बर्तनों का लेखक हूं। यह GitHub पर या PyPI पर पाया जा सकता है । यहां बताया गया है कि आप अपना उदाहरण कैसे प्रस्तुत कर सकते हैं:

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

6

datetime.datetimeतृतीय-पक्ष मॉड्यूल को स्थापित किए बिना सभी समर्थित Python संस्करणों में ISO 8601 जैसी दिनांक स्ट्रिंग को UNIX टाइमस्टैम्प या ऑब्जेक्ट में परिवर्तित करने का एक सीधा तरीका SQLite के दिनांक पार्सर का उपयोग करना है ।

#!/usr/bin/env python
from __future__ import with_statement, division, print_function
import sqlite3
import datetime

testtimes = [
    "2016-08-25T16:01:26.123456Z",
    "2016-08-25T16:01:29",
]
db = sqlite3.connect(":memory:")
c = db.cursor()
for timestring in testtimes:
    c.execute("SELECT strftime('%s', ?)", (timestring,))
    converted = c.fetchone()[0]
    print("%s is %s after epoch" % (timestring, converted))
    dt = datetime.datetime.fromtimestamp(int(converted))
    print("datetime is %s" % dt)

आउटपुट:

2016-08-25T16:01:26.123456Z is 1472140886 after epoch
datetime is 2016-08-25 12:01:26
2016-08-25T16:01:29 is 1472140889 after epoch
datetime is 2016-08-25 12:01:29

11
धन्यवाद। ये घटिया है। मुझे यह पसंद है।
वचर्गिन

1
क्या एक अविश्वसनीय, भयानक, सुंदर हैक! धन्यवाद!
हॉकोक

6

मैंने आईएसओ 8601 मानक के लिए एक पार्सर को कोडित किया है और इसे GitHub: https://github.com/boxed/iso8601 पर डाल दिया है । यह कार्यान्वयन पाइथन के डेटाटाइम मॉड्यूल की समर्थित तिथि सीमा के बाहर अवधि, अंतराल, आवधिक अंतराल और तिथियों को छोड़कर विनिर्देश में सब कुछ का समर्थन करता है।

टेस्ट शामिल हैं! : पी



6

Django के parse_datetime () फ़ंक्शन UTC ऑफ़सेट्स के साथ दिनांक का समर्थन करता है:

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

तो यह पूरे प्रोजेक्ट के भीतर खेतों में आईएसओ 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')

4

क्योंकि आईएसओ 8601 मूल रूप से मौजूद होने वाले वैकल्पिक कॉलन और डैश के कई रूपों की अनुमति देता है 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स्ट्रैप्टम निर्देश का समर्थन नहीं करता है (आप कुछ ऐसा देखते हैं ValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z') तो आपको मैन्युअल रूप से Z(यूटीसी) से समय को ऑफसेट करने की आवश्यकता है । नोट %zआपके सिस्टम पर अजगर संस्करणों में काम नहीं कर सकता है <3 जैसा कि यह c लाइब्रेरी सपोर्ट पर निर्भर है जो सिस्टम / अजगर बिल्ड टाइप (यानी ज्योन, साइथन, आदि) में भिन्न होता है।

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

2

2.X मानक लाइब्रेरी के साथ काम करने वाली किसी चीज़ के लिए:

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

Calendar.timegm time.mktime का गुम ग्राम संस्करण है।


1
यह सिर्फ टाइमज़ोन की उपेक्षा करता है '2013-01-28T14: 01: 01.335612-08: 00' -> यूटीसी के रूप में पार्स किया गया, न कि पीडीटी
गेटोतिग्रादो

2

अजवायन-खजूर एक अपवाद को फेंक देगा यदि अमान्य तारीख तार को पार्स कर रहा है, तो आप अपवाद को पकड़ना चाह सकते हैं।

from dateutil import parser
ds = '2012-60-31'
try:
  dt = parser.parse(ds)
except ValueError, e:
  print '"%s" is an invalid date' % ds


2

ISO-8601 के लिए विशेष पार्सर का उपयोग करने का एक और तरीका है , खजूर के पार्सर के आइसोपार्स फ़ंक्शन का उपयोग करना :

from dateutil import parser

date = parser.isoparse("2008-09-03T20:56:35.450686+01:00")
print(date)

आउटपुट:

2008-09-03 20:56:35.450686+01:00

इस समारोह में मानक पायथन फ़ंक्शन डेटटाइम के लिए प्रलेखन में भी उल्लेख किया गया है। Fromisoformat :

एक अधिक पूर्ण विशेषताओं वाला आईएसओ 8601 पार्सर, dateutil.parser.isoparse तीसरे पक्ष के पैकेज डेटाल में उपलब्ध है।


1

महान मार्क एमी के जवाब के लिए धन्यवाद, मैंने डेटाइम के सभी संभावित आईएसओ प्रारूपों के लिए खाता तैयार किया है:

class FixedOffset(tzinfo):
    """Fixed offset in minutes: `time = utc_time + utc_offset`."""
    def __init__(self, offset):
        self.__offset = timedelta(minutes=offset)
        hours, minutes = divmod(offset, 60)
        #NOTE: the last part is to remind about deprecated POSIX GMT+h timezones
        #  that have the opposite sign in the name;
        #  the corresponding numeric value is not used e.g., no minutes
        self.__name = '<%+03d%02d>%+d' % (hours, minutes, -hours)
    def utcoffset(self, dt=None):
        return self.__offset
    def tzname(self, dt=None):
        return self.__name
    def dst(self, dt=None):
        return timedelta(0)
    def __repr__(self):
        return 'FixedOffset(%d)' % (self.utcoffset().total_seconds() / 60)
    def __getinitargs__(self):
        return (self.__offset.total_seconds()/60,)

def parse_isoformat_datetime(isodatetime):
    try:
        return datetime.strptime(isodatetime, '%Y-%m-%dT%H:%M:%S.%f')
    except ValueError:
        pass
    try:
        return datetime.strptime(isodatetime, '%Y-%m-%dT%H:%M:%S')
    except ValueError:
        pass
    pat = r'(.*?[+-]\d{2}):(\d{2})'
    temp = re.sub(pat, r'\1\2', isodatetime)
    naive_date_str = temp[:-5]
    offset_str = temp[-5:]
    naive_dt = datetime.strptime(naive_date_str, '%Y-%m-%dT%H:%M:%S.%f')
    offset = int(offset_str[-4:-2])*60 + int(offset_str[-2:])
    if offset_str[0] == "-":
        offset = -offset
    return naive_dt.replace(tzinfo=FixedOffset(offset))

0
def parseISO8601DateTime(datetimeStr):
    import time
    from datetime import datetime, timedelta

    def log_date_string(when):
        gmt = time.gmtime(when)
        if time.daylight and gmt[8]:
            tz = time.altzone
        else:
            tz = time.timezone
        if tz > 0:
            neg = 1
        else:
            neg = 0
            tz = -tz
        h, rem = divmod(tz, 3600)
        m, rem = divmod(rem, 60)
        if neg:
            offset = '-%02d%02d' % (h, m)
        else:
            offset = '+%02d%02d' % (h, m)

        return time.strftime('%d/%b/%Y:%H:%M:%S ', gmt) + offset

    dt = datetime.strptime(datetimeStr, '%Y-%m-%dT%H:%M:%S.%fZ')
    timestamp = dt.timestamp()
    return dt + timedelta(hours=dt.hour-time.gmtime(timestamp).tm_hour)

ध्यान दें कि यदि स्ट्रिंग के साथ समाप्त नहीं होता है Z, तो हमें यह देखना चाहिए कि हम उपयोग कर सकते हैं %z


0

शुरू में मैंने इसके साथ प्रयास किया:

from operator import neg, pos
from time import strptime, mktime
from datetime import datetime, tzinfo, timedelta

class MyUTCOffsetTimezone(tzinfo):
    @staticmethod
    def with_offset(offset_no_signal, signal):  # type: (str, str) -> MyUTCOffsetTimezone
        return MyUTCOffsetTimezone((pos if signal == '+' else neg)(
            (datetime.strptime(offset_no_signal, '%H:%M') - datetime(1900, 1, 1))
          .total_seconds()))

    def __init__(self, offset, name=None):
        self.offset = timedelta(seconds=offset)
        self.name = name or self.__class__.__name__

    def utcoffset(self, dt):
        return self.offset

    def tzname(self, dt):
        return self.name

    def dst(self, dt):
        return timedelta(0)


def to_datetime_tz(dt):  # type: (str) -> datetime
    fmt = '%Y-%m-%dT%H:%M:%S.%f'
    if dt[-6] in frozenset(('+', '-')):
        dt, sign, offset = strptime(dt[:-6], fmt), dt[-6], dt[-5:]
        return datetime.fromtimestamp(mktime(dt),
                                      tz=MyUTCOffsetTimezone.with_offset(offset, sign))
    elif dt[-1] == 'Z':
        return datetime.strptime(dt, fmt + 'Z')
    return datetime.strptime(dt, fmt)

लेकिन यह नकारात्मक timezones पर काम नहीं किया। हालाँकि, मुझे ठीक काम मिला, अजगर में 3.7.3:

from datetime import datetime


def to_datetime_tz(dt):  # type: (str) -> datetime
    fmt = '%Y-%m-%dT%H:%M:%S.%f'
    if dt[-6] in frozenset(('+', '-')):
        return datetime.strptime(dt, fmt + '%z')
    elif dt[-1] == 'Z':
        return datetime.strptime(dt, fmt + 'Z')
    return datetime.strptime(dt, fmt)

कुछ परीक्षण, ध्यान दें कि आउट केवल माइक्रोसेकंड की सटीकता से भिन्न होता है। मेरी मशीन पर सटीकता के 6 अंक मिले, लेकिन YMMV:

for dt_in, dt_out in (
        ('2019-03-11T08:00:00.000Z', '2019-03-11T08:00:00'),
        ('2019-03-11T08:00:00.000+11:00', '2019-03-11T08:00:00+11:00'),
        ('2019-03-11T08:00:00.000-11:00', '2019-03-11T08:00:00-11:00')
    ):
    isoformat = to_datetime_tz(dt_in).isoformat()
    assert isoformat == dt_out, '{} != {}'.format(isoformat, dt_out)

क्या मैं पूछ सकता हूं कि आपने क्यों किया frozenset(('+', '-'))? क्या सामान्य टपल ('+', '-')को एक ही चीज़ को पूरा करने में सक्षम नहीं होना चाहिए ?
प्रहलाद यारी

ज़रूर, लेकिन यह नहीं है कि एक रेखीय स्कैन एक पूरी तरह से hashed लुकअप के बजाय?
एटी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.