ฉันจะแยกวิเคราะห์วันที่ในรูปแบบ ISO 8601 ได้อย่างไร


642

ฉันต้องการแยกสตริงRFC 3339"2008-09-03T20:56:35.450686Z"เป็นdatetimeประเภทของ Python

ฉันพบstrptimeในไลบรารีมาตรฐานของ Python แล้ว แต่ก็ไม่สะดวก

วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?




3
มีความชัดเจน: ISO 8601เป็นมาตรฐานหลัก RFC 3339เป็น“ โปรไฟล์” ที่ประกาศตัวเองของ ISO 8601 ซึ่งทำให้มีการแทนที่กฎISO 8601 ที่ไม่ฉลาด
Basil Bourque

3
อย่าพลาดโซลูชัน python3.7 + ด้านล่างนี้เพื่อแก้ปัญหา isoformat ()
แบรดเอ็ม

2
ไม่ควรปิดคำถามนี้เนื่องจากเป็นคำตอบของโพสต์ที่ลิงก์ เนื่องจากอันนี้ขอให้แยกสตริงเวลา ISO 8601 (ซึ่งไม่ได้รับการสนับสนุนโดย python ก่อนถึง 3.7) และอีกอันคือการจัดรูปแบบวัตถุ datetime ลงในสายยุคโดยใช้วิธีการล้าสมัย
abccd

คำตอบ:


462

หลาม dateutilแพคเกจสามารถแยกไม่เพียง แต่ RFC 3339 สตริง datetime อย่างหนึ่งในคำถาม แต่ยังอื่น ๆISO 8601วันที่และเวลาสตริงที่ไม่สอดคล้องกับ RFC 3339 (เช่นคนที่ไม่มีเวลา UTC ชดเชยหรือคนที่เป็นตัวแทนของ เฉพาะวันที่)

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

หากคุณกำลังใช้งูหลาม 3.7 มีลักษณะที่คำตอบนี้datetime.datetime.fromisoformatเกี่ยวกับ


75
สำหรับคนขี้เกียจก็ติดตั้งผ่านpython-dateutilไม่ได้ดังนั้น:dateutil pip install python-dateutil
cod3monk3y

29
ถูกเตือนว่าdateutil.parserเป็นแฮ็คที่ตั้งใจ: มันพยายามที่จะคาดเดารูปแบบและทำให้สมมติฐานที่หลีกเลี่ยงไม่ได้ (ปรับแต่งด้วยมือเท่านั้น) ในกรณีที่คลุมเครือ ดังนั้นใช้เฉพาะเมื่อคุณจำเป็นต้องวิเคราะห์อินพุตของรูปแบบที่ไม่รู้จักและไม่เป็นไรที่จะยอมรับความผิดที่เกิดขึ้นเป็นครั้งคราว
ivan_pozdeev

2
ตกลง ตัวอย่างคือการผ่าน "วันที่" ของ 9999 ซึ่งจะส่งกลับเช่นเดียวกับวันที่และเวลา (9999, เดือนปัจจุบัน, วันปัจจุบัน) ไม่ใช่วันที่ที่ถูกต้องในมุมมองของฉัน
timbo

1
@ivan_pozdeev แพ็คเกจใดที่คุณจะแนะนำสำหรับการแยกวิเคราะห์ที่ไม่คาดเดา
bgusach

2
@ivan_pozdeev มีการอัปเดตสำหรับโมดูลที่อ่าน iso8601 วันที่: dateutil.readthedocs.io/th/stable/…
theEpsilon

196

ใหม่ใน Python 3.7+


ห้องสมุดมาตรฐานแนะนำฟังก์ชั่นสำหรับการกลับหัวdatetimedatetime.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]]]]

ซึ่ง*สามารถจับคู่อักขระเดี่ยวใดก็ได้

ข้อควรระวัง : สิ่งนี้ไม่สนับสนุนการแยกสตริง ISO 8601 โดยพลการ - มันมีไว้สำหรับการดำเนินการแบบผกผันdatetime.isoformat()เท่านั้น

ตัวอย่างการใช้งาน:

from datetime import datetime

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

6
แปลก. เนื่องจาก a datetimeอาจมี a tzinfoและส่งออกเขตเวลา แต่datetime.fromisoformat()ไม่ได้แยกวิเคราะห์ tzinfo หรือไม่ ดูเหมือนว่าจะเป็นข้อผิดพลาด ..
Hendy Irawan

20
พลาดไม่ได้ทราบว่าในเอกสารนี้ไม่ได้รับทั้งหมดที่ถูกต้องตามมาตรฐาน ISO 8601 isoformatสตริงคนเดียวที่สร้างขึ้นโดย มันไม่ยอมรับตัวอย่างในคำถาม"2008-09-03T20:56:35.450686Z"เพราะต่อท้ายแต่มันก็ไม่ยอมรับZ "2008-09-03T20:56:35.450686"
Flimm

26
ให้การสนับสนุนอย่างถูกต้องสคริปต์การป้อนข้อมูลที่สามารถแก้ไขได้ด้วยZ date_string.replace("Z", "+00:00")
jox

7
โปรดทราบว่าสำหรับวินาทีมันจัดการได้เฉพาะทศนิยม 0, 3 หรือ 6 ตำแหน่งเท่านั้น หากข้อมูลอินพุตมีตำแหน่งทศนิยม 1, 2, 4, 5, 7 หรือมากกว่านั้นการแยกวิเคราะห์จะล้มเหลว!
Felk

1
@JDOaktown ตัวอย่างนี้ใช้ไลบรารี datetime ของไพ ธ อนไม่ใช่ parser ของ dateutil จริง ๆ แล้วมันจะล้มเหลวถ้าตำแหน่งทศนิยมไม่ใช่ 0, 3, หรือ 6 ด้วยวิธีนี้
abccd

174

หมายเหตุใน Python 2.6+ และ Py3K อักขระ% f จับไมโครวินาที

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

ดูปัญหาที่นี่


4
หมายเหตุ - หากใช้ชุดข้อมูล Naive - ฉันคิดว่าคุณจะไม่ได้รับ TZ เลย - Z อาจไม่ตรงกับสิ่งใดเลย
Danny Staple

24
คำตอบนี้ (ในรูปแบบปัจจุบันที่แก้ไข) อาศัยการกำหนดรหัสออฟเซ็ต UTC เฉพาะ (เช่น "Z" ซึ่งหมายถึง +00: 00) ลงในสตริงรูปแบบ นี่เป็นความคิดที่ไม่ดีเพราะมันจะล้มเหลวในการแยกวิเคราะห์วันที่และเวลาด้วย UTC ตรงข้ามที่แตกต่างกันและยกข้อยกเว้น ดูคำตอบของฉันที่อธิบายถึงวิธีการแยกวิเคราะห์ RFC 3339 ด้วยstrptimeในความเป็นจริงเป็นไปไม่ได้
Mark Amery

1
ในกรณีของฉัน% f จับ microseconds มากกว่า Z datetime.datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f') ดังนั้นนี่จึงเป็นกลอุบาย
ashim888

Py3K หมายถึง Python 3000 หรือไม่?
Robino

2
@Robino IIRC, "Python 3000" เป็นชื่อเดิมของสิ่งที่เรียกว่า Python 3
ทิ้งบัญชี

161

หลาย คำตอบ ที่นี่ ขอแนะนำให้ใช้datetime.datetime.strptimeการแยก RFC 3339 หรือ ISO 8601 datetimes กับเขตเวลา, เช่นเดียวกับการจัดแสดงในคำถาม:

2008-09-03T20:56:35.450686Z

นี่เป็นความคิดที่ไม่ดี

สมมติว่าคุณต้องการสนับสนุนรูปแบบ RFC 3339 เต็มรูปแบบรวมถึงการสนับสนุน UTC ออฟเซ็ตนอกเหนือจากศูนย์จากนั้นโค้ดที่คำตอบเหล่านี้แนะนำไม่ทำงาน อันที่จริงมันไม่สามารถทำงานได้เนื่องจากการแยกวิเคราะห์ไวยากรณ์ RFC 3339 ที่ใช้strptimeเป็นไปไม่ได้ สตริงรูปแบบที่ใช้โดยโมดูลวันที่และเวลาของ Python ไม่สามารถอธิบายไวยากรณ์ RFC 3339 ได้

ปัญหาคือ UTC ออฟเซ็ต RFC 3339 อินเทอร์เน็ตวันที่ / รูปแบบเวลากำหนดให้ทุกวันที่เวลารวมถึงการชดเชย UTC และชดเชยผู้ที่สามารถเป็นได้ทั้ง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ไม่มีคำสั่งที่สอดคล้องกับ UTC offsets ในรูปแบบ RFC 3339 รายการคำสั่งที่สมบูรณ์ที่สนับสนุนสามารถดูได้ที่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'

(ที่จริงแล้วข้างต้นเป็นเพียงสิ่งที่คุณจะเห็นใน Python 3 ใน Python 2 เราจะล้มเหลวด้วยเหตุผลที่ง่ายกว่าซึ่งก็คือมันstrptimeไม่ได้ใช้%zคำสั่งเลยใน Python 2 )

คำตอบมากมายที่นี่ซึ่งแนะนำให้แก้ไขstrptimeทั้งหมดนี้โดยรวมตัวอักษรZในสตริงรูปแบบซึ่งตรงกับZสตริง datetime ตัวอย่างจากคำถามของผู้ถาม (และทิ้งไว้ให้ผลิต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)

เนื่องจากสิ่งนี้จะทิ้งข้อมูลเขตเวลาที่รวมอยู่ในสตริง datetime ดั้งเดิมจึงเป็นที่น่าสงสัยว่าเราควรคำนึงถึงผลลัพธ์ที่ถูกต้องหรือไม่ แต่ที่สำคัญกว่านั้นเพราะวิธีนี้เกี่ยวข้องกับการเข้ารหัส UTC เฉพาะที่ชดเชยลงในสตริงรูปแบบมันจะทำให้หายใจไม่ออกในขณะที่พยายามแยกวิเคราะห์ RFC 3339 datetime ด้วย UTC offset ที่แตกต่างกัน:

>>> 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 datetimes ในเวลาซูลูและไม่ได้คนที่มีการชดเชยเขตอื่น ๆ strptimeที่ไม่ได้ใช้ ใช้หนึ่งในวิธีการอื่น ๆ อีกมากมายที่อธิบายไว้ในคำตอบที่นี่แทน


79
มันเป็นเรื่องที่น่าตื่นเต้นเพราะทำไม strptime จึงไม่มีคำสั่งสำหรับข้อมูลเขตเวลาของรูปแบบ ISO และทำไมถึงไม่สามารถแยกวิเคราะห์ได้ เหลือเชื่อ
Csaba Toth

2
@CsabaToth เห็นด้วยทั้งหมด - ถ้าฉันมีเวลาฆ่าบางทีฉันอาจลองเพิ่มมันเข้าไปในภาษา หรือคุณสามารถทำได้ถ้าคุณมีความโน้มเอียง - ฉันเห็นว่าคุณมีประสบการณ์ C บางอย่างซึ่งแตกต่างจากฉัน
Mark Amery

1
@CsabaToth - ทำไมถึงเหลือเชื่อ? มันทำงานได้ดีพอสำหรับคนส่วนใหญ่หรือพวกเขาพบวิธีแก้ปัญหาง่ายพอ หากคุณต้องการคุณสมบัติมันเป็น opensource และคุณสามารถเพิ่มได้ หรือจ่ายให้คนอื่นทำเพื่อคุณ ทำไมบางคนควรอาสาเวลาว่างของเขาเองเพื่อแก้ปัญหาเฉพาะของคุณ ให้แหล่งข่าวอยู่กับคุณ
Peter M. - ย่อมาจาก Monica

2
@PeterMasiar เหลือเชื่อเพราะมักจะพบว่าสิ่งที่อยู่ในหลามได้รับการดำเนินการอย่างรอบคอบและเต็มที่ เราได้รับความสนใจอย่างล้นหลามจากรายละเอียดนี้และเมื่อเราสะดุดบางสิ่งบางอย่างในภาษาที่เป็น "unpythonic" เราจึงโยนของเล่นของเราออกจากเรือท้องแบนเนื่องจากฉันกำลังจะทำตอนนี้ Whaaaaaaaaaa Whaa wahaaaaa :-(
Robino

2
strptime()ใน Python 3.7 ตอนนี้รองรับทุกสิ่งที่อธิบายว่าเป็นไปไม่ได้ในคำตอบนี้ ('Z' ตามตัวอักษรและ ':' ในออฟเซ็ตเขตเวลา) น่าเสียดายที่ยังมีอีกกรณีหนึ่งที่ทำให้ RFC 3339 ไม่สามารถใช้งานร่วมกับ ISO 8601 ได้ซึ่งโดยพื้นฐานแล้วในอดีตจะอนุญาตให้เขตเวลาว่างในเชิงลบเป็นค่าชดเชย -00: 00 และในภายหลังไม่ได้
SergiyKolesnikov

75

ลองใช้โมดูลiso8601 มันทำอย่างนี้

มีตัวเลือกอื่น ๆ หลายตัวที่กล่าวถึงในหน้าWorkingWithTimeบนวิกิ python.org


ง่ายเหมือนiso8601.parse_date("2008-09-03T20:56:35.450686Z")
Pakman

3
คำถามไม่ใช่ "ฉันจะแยกวันที่ ISO 8601 ได้อย่างไร" เป็น "ฉันจะแยกรูปแบบวันที่ที่แน่นอนนี้ได้อย่างไร"
Nicholas Riley

3
@tiktak OP ถามว่า "ฉันต้องแยกสตริงเหมือน X" และคำตอบของฉันเมื่อลองทั้งสองไลบรารีคือใช้อีกไลบรารีหนึ่งเนื่องจาก iso8601 ยังคงมีปัญหาสำคัญที่เปิดอยู่ การมีส่วนร่วมหรือขาดของโครงการดังกล่าวไม่เกี่ยวข้องกับคำตอบอย่างสมบูรณ์
เบีย

2
โปรดทราบว่ารุ่น pip ของ iso8601 ยังไม่ได้รับการอัปเดตตั้งแต่ปี 2550 และมีข้อบกพร่องร้ายแรงที่โดดเด่น ฉันขอแนะนำให้คุณใช้โปรแกรมแก้ไขที่สำคัญของตัวคุณเองหรือหาหนึ่งใน Github ส้อมที่ทำมาแล้วเช่นgithub.com/keithhackbarth/pyiso8601-strict
keithhackbarth

6
iso8601หรือที่รู้จักในชื่อpyiso8601ได้รับการอัพเดตเมื่อเร็ว ๆ นี้ในเดือนกุมภาพันธ์ 2014 เวอร์ชั่นล่าสุดรองรับชุด ISO 8601 ที่กว้างขึ้น ฉันเคยใช้เพื่อผลดีในบางโครงการของฉัน
เดฟไฮน์

34
นำเข้าอีกครั้ง datetime
s = "2008-09-03T20: 56: 35.450686Z"
d = datetime.datetime (* map (int, re.split ('[^ \ d]', s) [: - 1])

73
ฉันไม่เห็นด้วยนี่เป็นสิ่งที่อ่านไม่ได้ในทางปฏิบัติและเท่าที่ฉันสามารถบอกได้ว่าไม่คำนึงถึง Zulu (Z) ซึ่งทำให้ช่วงเวลานี้ไร้เดียงสาแม้ว่าจะมีการจัดเตรียมข้อมูลเขตเวลาไว้ก็ตาม
umbrae

14
ฉันคิดว่ามันอ่านได้ค่อนข้างมาก ความจริงแล้วอาจเป็นวิธีที่ง่ายที่สุดและมีประสิทธิภาพที่สุดในการแปลงโดยไม่ต้องติดตั้งแพ็คเกจเพิ่มเติม
เบี

2
นี่เทียบเท่า d = datetime.datetime (* map (int, re.split ('\ D', s) [: - 1])) ฉันคิดว่า
Xuan

4
รูปแบบ:datetime.datetime(*map(int, re.findall('\d+', s))
jfs

3
สิ่งนี้ส่งผลให้วัตถุไร้เดียงสา datetime ไม่มีเขตเวลาใช่มั้ย ดังนั้นบิต UTC หายไปในการแปล?
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
Alexander Artemenko

วัตถุ datetime ธรรมดาไม่มีแนวคิดของเขตเวลา หากเวลาทั้งหมดของคุณลงท้ายด้วย "Z" ชุดข้อมูลทั้งหมดที่คุณได้รับคือ UTC (เวลาซูลู)
tzot

หากเขตเวลาเป็นสิ่งอื่นนอกจาก""หรือ"Z"จะต้องเป็นออฟเซ็ตเป็นชั่วโมง / นาทีซึ่งสามารถเพิ่ม / ลบออกจากวัตถุ datetime ได้โดยตรง คุณสามารถสร้างคลาสย่อย tzinfo เพื่อจัดการมัน แต่นั่นอาจจะไม่แนะนำอีกครั้ง
SingleNegationElimination

8
นอกจากนี้ "% f" เป็นตัวระบุ microsecond ดังนั้นสตริง strptime (เขตเวลาไร้เดียงสา) จึงดูเหมือน: "% Y-% m-% dT% H:% M:% S. % f"
quodlibetor

1
สิ่งนี้จะเพิ่มข้อยกเว้นหากสตริงเวลาที่กำหนดและเวลามี UTC ตรงข้ามที่ไม่ใช่ "Z" ไม่รองรับรูปแบบ RFC 3339 ทั้งหมดและเป็นคำตอบที่ด้อยกว่าสำหรับผู้อื่นที่จัดการ UTC ออฟเซ็ตอย่างถูกต้อง
Mark Amery

25

เริ่มต้นจาก Python 3.7, strptime รองรับตัวคั่นลำไส้ใหญ่ใน UTC ออฟเซ็ต ( แหล่งที่มา ) ดังนั้นคุณสามารถใช้:

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

แก้ไข:

ดังที่ Martijn ชี้ให้เห็นถ้าคุณสร้างวัตถุ datetime โดยใช้ isoformat () คุณก็สามารถใช้ datetime ได้จาก isoformat ()


4
แต่ใน 3.7 คุณยังมีที่จับสายเช่นการป้อนข้อมูลของคุณโดยอัตโนมัติ:datetime.fromisoformat() datetime.datetime.isoformat('2018-01-31T09:24:31.488670+00:00')
Martijn Pieters

2
จุดดี. ฉันเห็นด้วยฉันแนะนำให้ใช้datetime.fromisoformat()และdatetime.isoformat()
Andreas Profous

19

ในวันนี้Arrowสามารถใช้เป็นโซลูชันของบุคคลที่สามได้:

>>> 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
Arrow ไม่รองรับ ISO8601 อย่างถูกต้องแม้ว่า: github.com/crsmithdev/arrow/issues/291
บรรจุกล่อง

1
เพียงใช้ python-dateutil - ลูกศรต้องใช้ python-dateutil
danizen

Arrow ตอนนี้รองรับ ISO8601 ปัญหาที่อ้างอิงถูกปิดตอนนี้
Altus

18

เพียงแค่ใช้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
@Flimms นี้ไม่ได้ตอบด้านบนใช่หรือไม่
สิงห์

1
คุณเห็นเขาแยกวิเคราะห์ที่ไหนในไม่กี่วินาที? ฉันพบบทความนี้โดยพยายามใช้เวลาเพื่อให้ฉันคิดว่าคนอื่นจะเป็นเช่นกัน
Blairg23

1
นี่ไม่ใช่ UTC ในระบบของฉัน แต่ผลลัพธ์ในหน่วยวินาทีเป็นเวลา unix epoch ราวกับว่าวันที่อยู่ในเขตเวลาท้องถิ่นของฉัน
Elliot

1
คำตอบนี้เป็นข้อผิดพลาดและไม่ควรยอมรับ น่าจะเป็นคำถามทั้งหมดควรถูกทำเครื่องหมายว่าซ้ำกับstackoverflow.com/questions/11743019/…
tripleee

@tripleee ที่จริงฉันเพิ่งตรวจสอบรหัสและดูเหมือนว่าจะกลับคำตอบที่ถูกต้อง: 455051100(ตรวจสอบที่epochconverter.com ) ,,, เว้นแต่ฉันจะหายไปบางสิ่งบางอย่าง?
Blairg23

13

หากคุณไม่ต้องการใช้ 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)

5
คำตอบนี้อาศัยยากเข้ารหัส UTC โดยเฉพาะอย่างยิ่งการชดเชย (คือ "Z" ซึ่งหมายความว่า 00: 00) strptimeเข้ามาในรูปแบบของสตริงที่ผ่านมา นี่เป็นความคิดที่ไม่ดีเพราะมันจะล้มเหลวในการแยกวิเคราะห์วันที่และเวลาด้วย UTC ตรงข้ามที่แตกต่างกันและยกข้อยกเว้น ดูคำตอบของฉันที่อธิบายถึงวิธีการแยกวิเคราะห์ RFC 3339 ด้วย strptime ในความเป็นจริงเป็นไปไม่ได้
Mark Amery

1
มันเป็นรหัสยาก แต่ก็เพียงพอสำหรับกรณีเมื่อคุณต้องการแยกซูลูเท่านั้น
Sasha

1
@alexander ใช่ - ซึ่งอาจเป็นกรณีตัวอย่างเช่นคุณรู้ว่าสตริงวันที่ของคุณถูกสร้างขึ้นด้วยtoISOStringวิธีการของ JavaScript แต่ไม่มีการกล่าวถึงการ จำกัด เวลาวันที่ของซูลูในคำตอบนี้และคำถามก็ไม่ได้ระบุว่าเป็นสิ่งที่จำเป็นและการใช้เพียงแค่dateutilสะดวกและเท่ากันในสิ่งที่สามารถแยกวิเคราะห์ได้
Mark Amery

11

หากคุณทำงานกับ Django จะมีโมดูล dateparseที่ยอมรับรูปแบบที่คล้ายกับรูปแบบ ISO รวมถึงเขตเวลา

หากคุณไม่ได้ใช้ Django และคุณไม่ต้องการใช้หนึ่งในห้องสมุดอื่น ๆ ที่กล่าวถึงในที่นี้คุณอาจปรับซอร์สโค้ด Django สำหรับ dateparseให้กับโครงการของคุณ


Django DateTimeFieldใช้สิ่งนี้เมื่อคุณตั้งค่าสตริง
djvg

11

ฉันพบว่าciso8601เป็นวิธีที่เร็วที่สุดในการวิเคราะห์เวลา ISO 8601 ตามชื่อที่แนะนำมันถูกนำไปใช้ใน C

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

GitHub Repo READMEแสดงให้เห็นว่าพวกเขา> 10 เท่าเมื่อเทียบกับการเพิ่มความเร็วทั้งหมดของห้องสมุดอื่น ๆ ที่ระบุไว้ในคำตอบอื่น ๆ

โครงการส่วนบุคคลของฉันเกี่ยวข้องกับการแยก ISO 8601 จำนวนมาก มันดีที่จะสามารถเปลี่ยนสายและไปเร็วขึ้น 10 เท่า :)

แก้ไข:ฉันได้กลายเป็นผู้ดูแลของ ciso8601 เร็วขึ้นกว่าเดิม!


ดูเหมือนห้องสมุดที่ยอดเยี่ยม! สำหรับผู้ที่ต้องการเพิ่มประสิทธิภาพการแยก ISO8601 บน Google App Engine น่าเศร้าที่เราไม่สามารถใช้มันเพราะมันเป็นห้องสมุด C แต่มาตรฐานของคุณมีความชาญฉลาดเพื่อแสดงให้เห็นว่าภาษาdatetime.strptime()เป็นวิธีแก้ปัญหาที่เร็วที่สุดต่อไป ขอบคุณที่รวบรวมข้อมูลทั้งหมดเข้าด้วยกัน!
hamx0r

3
@ hamx0r โปรดระวังว่าdatetime.strptime()ไม่ใช่ไลบรารีการแยกวิเคราะห์ ISO 8601 ที่สมบูรณ์ หากคุณใช้ Python 3.7 คุณสามารถใช้datetime.fromisoformat()วิธีนี้ซึ่งยืดหยุ่นกว่าเล็กน้อย คุณอาจสนใจรายการ parsersที่สมบูรณ์ยิ่งขึ้นซึ่งควรจะรวมเข้ากับ ciso8601 README ในไม่ช้า
movermeyer

ciso8601 ทำงานได้ค่อนข้างดี แต่ก่อนอื่นต้องทำ "pip install pytz" ก่อนเพราะจะไม่สามารถแยกเวลาประทับที่มีข้อมูลโซนเวลาโดยไม่ต้องพึ่งพา pytz ตัวอย่างจะมีลักษณะเช่น: dob = ciso8601.parse_datetime (ผลลัพธ์ ['dob'] ['date'])
Dirk

2
@Dirk, เพียงในหลาม 2 แต่ถึงอย่างนั้นก็ควรจะลบออกในรุ่นถัดไป
movermeyer

8

ใช้งานได้กับ 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
คำตอบนี้อาศัยยากเข้ารหัส UTC โดยเฉพาะอย่างยิ่งการชดเชย (คือ "Z" ซึ่งหมายความว่า 00: 00) strptimeเข้ามาในรูปแบบของสตริงที่ผ่านมา นี่เป็นความคิดที่ไม่ดีเพราะมันจะล้มเหลวในการแยกวิเคราะห์วันที่และเวลาด้วย UTC ตรงข้ามที่แตกต่างกันและยกข้อยกเว้น ดูคำตอบของฉันที่อธิบายถึงวิธีการแยกวิเคราะห์ RFC 3339 ด้วย strptime ในความเป็นจริงเป็นไปไม่ได้
Mark Amery

1
ในทางทฤษฎีใช่สิ่งนี้ล้มเหลว ในทางปฏิบัติฉันไม่เคยพบกับวันที่จัดรูปแบบ ISO 8601 ซึ่งไม่ได้อยู่ในเวลาซูลู สำหรับความต้องการของฉันเป็นครั้งคราวสิ่งนี้ใช้ได้ดีและไม่พึ่งพาห้องสมุดภายนอกบางแห่ง
Benjamin Riggs

4
คุณสามารถใช้แทนtimezone.utc timezone(timedelta(0))นอกจากนี้รหัสทำงานใน Python 2.6+ (อย่างน้อย) หากคุณจัดหาutcออบเจ็กต์ tzinfo
jfs

ไม่สำคัญว่าคุณจะพบมันไม่ตรงกับสเป็ค
theannouncer

คุณสามารถใช้%Zสำหรับเขตเวลาใน Python เวอร์ชันล่าสุด
sventechie

7

ฉันเป็นผู้เขียน iso8601 utils มันสามารถพบได้บน GitHubหรือบนPyPI นี่คือวิธีที่คุณสามารถแยกวิเคราะห์ตัวอย่างของคุณ:

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

6

วิธีการหนึ่งที่ตรงไปตรงมาแปลงเป็น ISO 8601 เหมือนสตริงวันกับเวลาในยูนิกซ์หรือdatetime.datetimeวัตถุในทุกรุ่นที่รองรับหลามโดยไม่ต้องติดตั้งโมดูลของบุคคลที่สามคือการใช้ตัวแยกวิเคราะห์วันที่ 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
ขอบคุณ สิ่งนี้น่าขยะแขยง ฉันรักมัน.
wchargin

1
ช่างเป็นการแฮ็กข้อมูลที่เหลือเชื่อน่ากลัวและสวยงามมาก! ขอบคุณ!
Havok

6

ผมเคยขึ้นรหัส parser สำหรับมาตรฐาน ISO 8601 และวางไว้บน GitHub: https://github.com/boxed/iso8601 การใช้งานนี้รองรับทุกอย่างในข้อกำหนดยกเว้นช่วงเวลาช่วงเวลาและวันที่ที่อยู่นอกช่วงวันที่ที่สนับสนุนของโมดูลวันที่และเวลาของ Python

รวมการทดสอบแล้ว! : P


2
โดยทั่วไปการเชื่อมโยงไปยังเครื่องมือหรือไลบรารีควรมาพร้อมกับบันทึกการใช้งานคำอธิบายเฉพาะเกี่ยวกับวิธีการใช้ทรัพยากรที่เชื่อมโยงกับปัญหาหรือโค้ดตัวอย่างบางส่วนหรือถ้าเป็นไปได้ทั้งหมดข้างต้น
Samuel Liew

6

ฟังก์ชัน 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')

4

เพราะมาตรฐาน ISO 8601 CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]ช่วยให้หลายรูปแบบของทวิภาคตัวเลือกและพุ่งเป็นปัจจุบันโดยทั่วไป หากคุณต้องการใช้ strptime คุณจะต้องตัดการเปลี่ยนแปลงเหล่านั้นออกก่อน

เป้าหมายคือการสร้างวัตถุ utc datetime


หากคุณต้องการกรณีพื้นฐานที่ทำงานกับ 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คำสั่ง strptime (คุณเห็นสิ่งที่ต้องการValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z') จากนั้นคุณต้องชดเชยเวลาด้วยตนเองZ(UTC) หมายเหตุ%zอาจใช้งานไม่ได้กับระบบของคุณในเวอร์ชันหลาม <3 เนื่องจากมันขึ้นอยู่กับการรองรับไลบรารี c ซึ่งแตกต่างกันไปตามประเภทการสร้างระบบ / หลาม (เช่น 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

2

สำหรับสิ่งที่ใช้ได้กับไลบรารี่มาตรฐาน 2.X ลอง:

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

calendar.timegm เป็นรุ่น gm ที่ขาดหายไปของ time.mktime


1
นี่เป็นเพียงการข้ามเขตเวลา '2013-01-28T14: 01: 01.335612-08: 00' -> แยกวิเคราะห์เป็น UTC ไม่ใช่ PDT
gatoatigrado

2

หลาม -thututil จะโยนข้อยกเว้นถ้าแยกสตริงวันที่ไม่ถูกต้องดังนั้นคุณอาจต้องการที่จะจับข้อยกเว้น

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

2

ทุกวันนี้มีMaya: Datetimes for Humans ™จากผู้เขียนคำขอยอดนิยม: แพ็คเกจ HTTP for Humans ™:

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

2

วิธีหนึ่งคือการใช้ตัวแยกวิเคราะห์เฉพาะสำหรับ ISO-8601 คือการใช้isoparseการทำงานของ parser dateutil:

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

ฟังก์ชั่นนี้ถูกกล่าวถึงในเอกสารประกอบสำหรับฟังก์ชั่น Python มาตรฐานdatetime จากรูปแบบ :

ตัวแยกวิเคราะห์ ISO 8601 ที่มีคุณลักษณะครบถ้วนมากขึ้น dateutil.parser.isoparse มีอยู่ใน dateutil ของแพ็คเกจบุคคลที่สาม


1

ขอบคุณคำตอบของ Mark Ameryที่ยอดเยี่ยมฉันได้คิดหน้าที่การใช้งานสำหรับรูปแบบ ISO ที่เป็นไปได้ของ datetime

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)

แต่นั่นไม่ได้ผลกับเขตเวลาเชิงลบ อย่างไรก็ตามฉันทำงานได้ดีใน Python 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(('+', '-'))ไหมว่าทำไมคุณถึงทำ tuple ปกติไม่ควร('+', '-')จะสามารถทำสิ่งเดียวกันได้หรือไม่?
Prahlad Yeri

แน่นอน แต่นั่นไม่ใช่การสแกนเชิงเส้นแทนที่จะเป็นการค้นหาที่แฮ็กอย่างสมบูรณ์หรือ
AT
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.