मुझे पायथन के प्रकार की तरह RFC 3339 स्ट्रिंग्स को पार्स करने की आवश्यकता है ।"2008-09-03T20:56:35.450686Z"
datetime
मैंने strptime
पायथन मानक पुस्तकालय में पाया है, लेकिन यह बहुत सुविधाजनक नहीं है।
इसे करने का बेहतरीन तरीका क्या है?
मुझे पायथन के प्रकार की तरह RFC 3339 स्ट्रिंग्स को पार्स करने की आवश्यकता है ।"2008-09-03T20:56:35.450686Z"
datetime
मैंने strptime
पायथन मानक पुस्तकालय में पाया है, लेकिन यह बहुत सुविधाजनक नहीं है।
इसे करने का बेहतरीन तरीका क्या है?
जवाबों:
अजगर-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
।
python-dateutil
नहीं dateutil
है, तो: pip install python-dateutil
।
dateutil.parser
जानबूझकर हैक किया गया है: यह प्रारूपण का अनुमान लगाने की कोशिश करता है और अस्पष्ट मामलों में अपरिहार्य धारणाएं (केवल हाथ से अनुकूलन) बनाता है। तो केवल इसका उपयोग करें यदि आपको अज्ञात प्रारूप के इनपुट को पार्स करने की आवश्यकता है और कभी-कभार होने वाली गड़बड़ियों को सहन करने के लिए ठीक है।
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')
datetime
इसमें एक शामिल हो सकता है tzinfo
, और इस तरह एक datetime.fromisoformat()
टाइमज़ोन आउटपुट हो सकता है , लेकिन tzinfo को पार्स नहीं करता है? एक बग की तरह लगता है ..
isoformat
। यह अनुगमन के "2008-09-03T20:56:35.450686Z"
कारण प्रश्न में उदाहरण को स्वीकार नहीं करता है Z
, लेकिन यह स्वीकार करता है "2008-09-03T20:56:35.450686"
।
Z
इनपुट स्क्रिप्ट का ठीक से समर्थन करने के लिए इसके साथ संशोधित किया जा सकता है date_string.replace("Z", "+00:00")
।
पायथन 2.6+ और Py3K में नोट,% f वर्ण माइक्रोसेकंड पकड़ता है।
>>> datetime.datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")
यहां देखें मुद्दा
strptime
करना वास्तव में कितना असंभव है।
datetime.datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f')
इसलिए इसने यह चाल
यहाँ कई उत्तर आरएफसी 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
। इसके बजाय उत्तर में वर्णित कई अन्य दृष्टिकोणों में से एक का उपयोग करें।
strptime()
पायथॉन 3.7 में अब इस उत्तर में असंभव ('जेड' शाब्दिक और ':' समय-सीमा में ऑफसेट) के रूप में वर्णित सब कुछ का समर्थन करता है। दुर्भाग्य से, एक और कोने का मामला है जो RFC 3339 को मूल रूप से आईएसओ 8601 के साथ असंगत बनाता है, अर्थात्, पूर्व एक नकारात्मक अशक्त timezone ऑफ़सेट -00: 00 और बाद में नहीं की अनुमति देता है।
Iso8601 मॉड्यूल की कोशिश करो ; यह ठीक यही करता है।
Python.org विकी पर वर्कविथ टाइम पेज पर कई अन्य विकल्पों का उल्लेख किया गया है ।
iso8601.parse_date("2008-09-03T20:56:35.450686Z")
आयात फिर, डेटाइम रों = "2008-09-03T20: 56: 35.450686Z" d = datetime.datetime (* map (int, re.split ('[^ \ d]', s) [: - 1])
datetime.datetime(*map(int, re.findall('\d+', s))
सटीक त्रुटि क्या है? यह निम्नलिखित की तरह है?
>>> 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)
""
या "Z"
है, तो यह घंटे / मिनट, जो सीधे करने के लिए / datetime वस्तु से घटाया जोड़ा जा सकता है में एक ऑफसेट किया जाना चाहिए। आप इसे संभालने के लिए एक tzinfo उपवर्ग बना सकते हैं, लेकिन यह संभव नहीं है।
पायथन 3.7 से शुरू, स्ट्रैपटाइम यूटीसी ऑफसेट्स ( स्रोत ) में कोलोन डेलिमिटर का समर्थन करता है । तो आप तब उपयोग कर सकते हैं:
import datetime
datetime.datetime.strptime('2018-01-31T09:24:31.488670+00:00', '%Y-%m-%dT%H:%M:%S.%f%z')
संपादित करें:
जैसा कि मार्टिज्न ने बताया है, अगर आपने आइसोफोर्मैट () का उपयोग करके डेटाइम ऑब्जेक्ट बनाया है, तो आप बस डेटाइम.फ्रेमिसोफॉर्म () का उपयोग कर सकते हैं
datetime.fromisoformat()
जो आपके इनपुट की तरह तार को स्वचालित रूप से संभालता है datetime.datetime.isoformat('2018-01-31T09:24:31.488670+00:00')
:।
datetime.fromisoformat()
औरdatetime.isoformat()
इन दिनों में, तीर का उपयोग तीसरे पक्ष के समाधान के रूप में भी किया जा सकता है:
>>> import arrow
>>> date = arrow.get("2008-09-03T20:56:35.450686Z")
>>> date.datetime
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
बस 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())
455051100
( epochconverter.com पर जाँच की गई ) ,,, जब तक मैं कुछ याद नहीं कर रहा हूँ?
यदि आप खजूर का उपयोग नहीं करना चाहते हैं, तो आप इस कार्य को आजमा सकते हैं:
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)
strptime
। यह एक बुरा विचार है क्योंकि यह किसी भी UTC ऑफसेट के साथ किसी भी डेटाटाइम को पार्स करने और एक अपवाद को बढ़ाने में विफल रहेगा। मेरा उत्तर देखें जो बताता है कि स्ट्रैचम के साथ RFC 3339 को पार्स करना वास्तव में असंभव है।
toISOString
विधि के साथ उत्पन्न हुई थी । लेकिन इस उत्तर में ज़ुलु समय की तारीखों तक सीमित होने का कोई उल्लेख नहीं है, और न ही प्रश्न ने संकेत दिया कि यह है कि सभी की जरूरत है, और बस का उपयोग dateutil
करना आमतौर पर उतना ही सुविधाजनक और कम संकीर्ण है जो इसे पार्स कर सकता है।
यदि आप Django के साथ काम कर रहे हैं, तो यह समय क्षेत्र सहित आईएसओ प्रारूप के समान स्वरूपों का एक गुच्छा स्वीकार करता है, जो डेटापार्स मॉड्यूल प्रदान करता है।
यदि आप Django का उपयोग नहीं कर रहे हैं और आप यहां बताए गए अन्य पुस्तकालयों में से किसी एक का उपयोग नहीं करना चाहते हैं, तो आप संभवतः अपनी परियोजना के लिए तिथि निर्धारण के लिए Django स्रोत कोड को अनुकूलित कर सकते हैं।
DateTimeField
जब आप एक स्ट्रिंग मान सेट करते हैं तो Django का उपयोग करता है।
मैंने आईएसओ 8601 टाइमस्टैम्प को पार्स करने का सबसे तेज़ तरीका ciso8601 पाया है । जैसा कि नाम से पता चलता है, इसे C में लागू किया गया है।
import ciso8601
ciso8601.parse_datetime('2014-01-09T21:48:00.921000+05:30')
GitHub रेपो README अन्य उत्तर में सूचीबद्ध अन्य पुस्तकालयों के सभी बनाम उनके> 10x speedup को दर्शाता है।
मेरी व्यक्तिगत परियोजना में आईएसओ 8601 पार्सिंग का एक बहुत कुछ शामिल था। बस कॉल स्विच करने और 10x तेज़ी से जाने में सक्षम होना अच्छा था। :)
संपादित करें: मैं तब से ciso8601 का अनुचर बन गया हूं। यह अब पहले से कहीं ज्यादा तेज है!
datetime.strptime()
अगला सबसे तेज समाधान है। उस जानकारी को एक साथ रखने के लिए धन्यवाद!
datetime.strptime()
पूर्ण आईएसओ 8601 पार्सिंग लाइब्रेरी नहीं है। यदि आप पायथॉन 3.7 पर हैं, तो आप datetime.fromisoformat()
विधि का उपयोग कर सकते हैं , जो थोड़ा अधिक लचीला है। आपको पार्सर्स की इस पूरी सूची में दिलचस्पी हो सकती है जिसे जल्द ही ciso8601 README में विलय कर दिया जाना चाहिए।
यह पाइथन 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)
strptime
। यह एक बुरा विचार है क्योंकि यह किसी भी UTC ऑफसेट के साथ किसी भी डेटाटाइम को पार्स करने और एक अपवाद को बढ़ाने में विफल रहेगा। मेरा उत्तर देखें जो बताता है कि स्ट्रैचम के साथ RFC 3339 को पार्स करना वास्तव में असंभव है।
timezone.utc
इसके बजाय उपयोग कर सकते हैं timezone(timedelta(0))
। इसके अलावा, यदि आप tzinfo ऑब्जेक्ट सप्लाईutc
%Z
पायथन के सबसे हाल के संस्करणों में टाइमज़ोन के लिए उपयोग कर सकते हैं ।
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
मैंने आईएसओ 8601 मानक के लिए एक पार्सर को कोडित किया है और इसे GitHub: https://github.com/boxed/iso8601 पर डाल दिया है । यह कार्यान्वयन पाइथन के डेटाटाइम मॉड्यूल की समर्थित तिथि सीमा के बाहर अवधि, अंतराल, आवधिक अंतराल और तिथियों को छोड़कर विनिर्देश में सब कुछ का समर्थन करता है।
टेस्ट शामिल हैं! : पी
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')
क्योंकि आईएसओ 8601 मूल रूप से मौजूद होने वाले वैकल्पिक कॉलन और डैश के कई रूपों की अनुमति देता है CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
। यदि आप स्ट्रैपटाइम का उपयोग करना चाहते हैं, तो आपको पहले उन विविधताओं को अलग करना होगा।
लक्ष्य एक utc डेटाटाइम ऑब्जेक्ट जनरेट करना है।
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.X मानक लाइब्रेरी के साथ काम करने वाली किसी चीज़ के लिए:
calendar.timegm(time.strptime(date.split(".")[0]+"UTC", "%Y-%m-%dT%H:%M:%S%Z"))
Calendar.timegm time.mktime का गुम ग्राम संस्करण है।
अजवायन-खजूर एक अपवाद को फेंक देगा यदि अमान्य तारीख तार को पार्स कर रहा है, तो आप अपवाद को पकड़ना चाह सकते हैं।
from dateutil import parser
ds = '2012-60-31'
try:
dt = parser.parse(ds)
except ValueError, e:
print '"%s" is an invalid date' % ds
आजकल माया है: इंसानों के लिए डेटाटम्स ™ , लोकप्रिय अनुरोधों के लेखक से: मानवजाति ™ पैकेज के लिए HTTP:
>>> import maya
>>> str = '2008-09-03T20:56:35.450686Z'
>>> maya.MayaDT.from_rfc3339(str).datetime()
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=<UTC>)
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 तीसरे पक्ष के पैकेज डेटाल में उपलब्ध है।
महान मार्क एमी के जवाब के लिए धन्यवाद, मैंने डेटाइम के सभी संभावित आईएसओ प्रारूपों के लिए खाता तैयार किया है:
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))
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
।
शुरू में मैंने इसके साथ प्रयास किया:
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(('+', '-'))
? क्या सामान्य टपल ('+', '-')
को एक ही चीज़ को पूरा करने में सक्षम नहीं होना चाहिए ?