การแปลงสตริงเป็น datetime


2181

ฉันมีรายการวันที่จำนวนมากเช่นนี้เป็นสตริง:

Jun 1 2005  1:33PM
Aug 28 1999 12:00AM

ฉันจะผลักพวกนี้กลับไปยังเขตข้อมูลวันที่และเวลาที่เหมาะสมในฐานข้อมูลดังนั้นฉันต้องเปลี่ยนพวกเขาให้เป็นวัตถุวันที่และเวลาจริง

นี่คือการผ่าน ORM ของ Django ดังนั้นฉันไม่สามารถใช้ SQL ในการแปลงกับการแทรก


6
หากคุณไม่แน่ใจว่ารูปแบบใดรูปแบบหนึ่งจัดการทุกวันที่เวลา (ไม่ '', ไม่มี NaNs, ไม่สมบูรณ์, ไม่มีรูปแบบที่ไม่ตรงกัน, ไม่มีตัวอักษรต่อท้าย, เขตเวลา, เวลาบันทึกไมโครวินาทีหรือข้อความอื่น ๆ ... ) strptime()จะขับถั่วให้คุณเว้นเสียแต่ว่าคุณจะหุ้มมัน ดูคำตอบของฉันตามคำตอบของ
Oris ตาม

วิธีที่ขี้เกียจและใช้งานได้อย่างกว้างขวางที่สุดที่ฉันรู้จักคือ dateparser (ตรวจสอบblog.scrapinghub.com/2015/11/09/… ) มันทำงานได้แม้จะมีการแสดงออกเวลาภาษาธรรมชาติในหลายภาษาออกจากกล่อง ฉันคิดว่ามันอาจจะช้า
อาร์มันโด

มีลิงค์ที่เป็นประโยชน์ที่นี่: stackabuse.com/converting-strings-to-datetime-in-python
GoingMyWay

คำตอบ:


3459

datetime.strptimeเป็นรูทีนหลักสำหรับการแยกสตริงลงในชุดข้อมูล มันสามารถจัดการทุกรูปแบบด้วยรูปแบบที่กำหนดโดยสตริงรูปแบบที่คุณกำหนด:

from datetime import datetime

datetime_object = datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

datetimeวัตถุที่เกิดขึ้นคือเขตเวลาไร้เดียงสา

ลิงค์:

  • เอกสาร Python สำหรับstrptime: Python 2 , Python 3

  • เอกสาร Python สำหรับstrptime/ strftimeสตริงรูปแบบ: Python 2 , Python 3

  • strftime.orgเป็นแหล่งอ้างอิงที่ดีมากสำหรับ strftime

หมายเหตุ:

  • strptime = "เวลาในการแยกสตริง"
  • strftime = "เวลารูปแบบสตริง"
  • ออกเสียงออกมาดัง ๆ วันนี้และคุณไม่ต้องค้นหาอีกใน 6 เดือน

7
'% b', '% p' ​​อาจล้มเหลวในภาษาที่ไม่ใช่ภาษาอังกฤษ
jfs

15
@ ผู้ใช้คุณจะต้องรู้ล่วงหน้าก่อนที่จะแยกส่วนของสตริงรูปแบบนั้น แต่ถ้าคุณต้องการdateแทนที่ a datetimeคุณจะต้องdatetimeจัดการมันแทน: datetime.strptime('Jun 1 2005', '%b %d %Y').date() == date(2005, 6, 1)
Izkata

14
หากคุณรู้ว่าสตริงแสดงวันที่และเวลาใน UTC คุณสามารถรับdatetimeวัตถุที่ทราบเขตเวลาโดยเพิ่มบรรทัดนี้ใน Python 3:from datetime import timezone; datetime_object = datetime_object.replace(tzinfo=timezone.utc)
Flimm

111
ฉันกำลังหา"%Y-%m-%d %H:%M:%S"
Martin Thoma

4
@AminahNuraini ฉันได้รอบปัญหาที่คล้ายกันโดยการทำแทนเพียงfrom datetime import datetime import datetime
Max Strater

831

ใช้ห้องสมุดdateutilบุคคลที่สาม:

from dateutil import parser
parser.parse("Aug 28 1999 12:00AM")  # datetime.datetime(1999, 8, 28, 0, 0)

มันสามารถจัดการรูปแบบวันที่ส่วนใหญ่รวมถึงรูปแบบที่คุณต้องแยกวิเคราะห์ สะดวกกว่าstrptimeที่จะคาดเดารูปแบบที่ถูกต้องเป็นส่วนใหญ่

มันมีประโยชน์มากสำหรับการเขียนแบบทดสอบที่การอ่านมีความสำคัญมากกว่าประสิทธิภาพ

คุณสามารถติดตั้งได้ด้วย:

pip install python-dateutil

86
โปรดทราบว่าสำหรับข้อมูลจำนวนมากสิ่งนี้อาจไม่ใช่วิธีที่ดีที่สุดในการแก้ไขปัญหา การเดารูปแบบทุกครั้งอาจช้าอย่างน่ากลัว
Paweł Polewicz

14
นี่เป็นสิ่งที่ดี แต่มันจะดีถ้ามีวิธีแก้ปัญหาในตัวแทนที่จะไปให้บุคคลที่สาม
brian buck

1
เมื่อฉันพยายามที่จะแยกวิเคราะห์ "32nd ม.ค. " มันส่งกลับฉัน "2032-01-06" .. ซึ่งไม่ถูกต้อง มีวิธีใดที่จะตรวจสอบว่าสตริงนั้นเป็นวันที่ที่ถูกต้องหรือไม่
Kartik Domadiya

6
@Reef: 5 ครั้งช้าตามมาตรฐานที่รวดเร็วและสกปรกของฉัน ไม่เช่นนั้นอย่างน่ากลัวช้าที่สุดเท่าที่ผมจะคาดหวัง
Antony Hatchkins

2
มีปัญหาของตัวเอง - เช่นวางข้อมูลเขตเวลาอย่างเงียบ ๆ จากเวลา: ลอง parser.parse ('15: 55EST ') และเปรียบเทียบกับ parser.parse ('15 .55CST') เป็นตัวอย่าง
F1Rumors

490

ตรวจสอบstrptimeในโมดูลเวลา มันเป็นสิ่งที่ตรงกันข้ามของstrftime

$ python
>>> import time
>>> my_time = time.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')
time.struct_time(tm_year=2005, tm_mon=6, tm_mday=1,
                 tm_hour=13, tm_min=33, tm_sec=0,
                 tm_wday=2, tm_yday=152, tm_isdst=-1)

timestamp = time.mktime(my_time)
# convert time object to datetime
from datetime import datetime
my_datetime = datetime.fromtimestamp(timestamp)
# convert time object to date
from datetime import date
my_date = date.fromtimestamp(timestamp)

16
จากสิ่งที่ฉันเข้าใจคำตอบนี้จะแสดงเฉพาะวัตถุเวลาไม่ใช่วัตถุ datetime ซึ่งเป็นสาเหตุที่คำตอบจะถูกฝังเมื่อเทียบกับคำตอบของ Patrick
Alexander Bird

มีวิธีการตั้งค่ารูปแบบวันที่และเวลาเริ่มต้นของ DateTimeField หรือไม่?
สำคัญ

3
ดังที่อเล็กซานเดอร์กล่าวกลับเป็น struct_time ไม่ใช่วันที่และเวลา แน่นอนคุณสามารถแปลงเป็นวันที่และเวลาได้ แต่คำตอบของ Patrick ตรงไปตรงมามากขึ้นถ้าคุณต้องการวัตถุ datetime ในท้ายที่สุด
Leandro Alves

ไม่มีอะไรที่เหมือนกับ strtotime ในไลบรารีไพ ธ อนมาตรฐาน แต่ dateutil มีตัวแยกวิเคราะห์ที่รู้จักรูปแบบวันที่พยายามมากที่สุด
Geoff Gerrietts

1
@BenBlank: '% b', '% p' ​​อาจล้มเหลวในภาษาที่ไม่ใช่ภาษาอังกฤษ
jfs

113

ฉันได้รวบรวมโครงการที่สามารถแปลงนิพจน์ที่ประณีตบางอย่าง ตรวจสอบtimestring

นี่คือตัวอย่างด้านล่าง:

pip install timestring
>>> import timestring
>>> timestring.Date('monday, aug 15th 2015 at 8:40 pm')
<timestring.Date 2015-08-15 20:40:00 4491909392>
>>> timestring.Date('monday, aug 15th 2015 at 8:40 pm').date
datetime.datetime(2015, 8, 15, 20, 40)
>>> timestring.Range('next week')
<timestring.Range From 03/10/14 00:00:00 to 03/03/14 00:00:00 4496004880>
>>> (timestring.Range('next week').start.date, timestring.Range('next week').end.date)
(datetime.datetime(2014, 3, 10, 0, 0), datetime.datetime(2014, 3, 14, 0, 0))

2
ว้าว. ว้าว. ว้าว. ว้าว. มันง่ายมาก ฉันมีสตริงวันที่และเวลาและฉันต้องการดึงออกปี ง่ายเหมือน: import timestring timestring.Date('27 Mar 2014 12:32:29 GMT').yearlib นี้ทำให้มันง่ายมาก! ขอบคุณ.
brandonjp

ยินดีอย่างยิ่ง. ฉันชอบความคิดเห็นและแนวคิดของคุณในการปรับปรุงแพ็คเกจนี้ แจ้งให้เราทราบใช้ปัญหา GitHub ขอบคุณ!
Steve Peak

สวัสดีสตีฟโมดูลดีมาก จะดีถ้ามีแอตทริบิวต์สายอักขระวันทำงานเช่นกัน มิฉะนั้นไม่แน่ใจว่าคุณจะเริ่มตั้งแต่วันจันทร์หรือวันอาทิตย์
Anake

1
ไม่แปลงเช่น '5 ก.พ. 2017' และ '5 กุมภาพันธ์ 2017' อย่างถูกต้อง (ซึ่งเป็นรูปแบบที่นิยมในบางแวดวงและ IMO ของรูปแบบวันที่ดีที่สุดสำหรับความชัดเจนและการอ่าน) 2017-02-01มันเก็บพวกเขาเป็น เหมือนกันสำหรับ 5 / Feb / 2017 (แต่ไม่ถูกต้อง ก.พ. / 5/2017 อย่างถูกต้อง); ทั้งสองรูปแบบสุดท้ายนั้นไม่ใช่รูปแบบที่ฉันเคยเห็นความรู้ของฉัน แต่ฉันคิดว่าฉันจะชี้ให้เห็น
Brōtsyorfuzthrāx

2
คำเตือน:แพคเกจนี้ดูเหมือนจะไม่ได้รับการบำรุงรักษาหรือปรับปรุงไม่ว่าจะในช่วง 5 ปีที่ผ่านมาและแยกวิเคราะห์วันที่ผิดปกติอย่างชัดเจน ยกตัวอย่างเช่น instantiating อย่างใดแยกวิเคราะห์ค่าของDate("20180912") 2018-11-21ใช้ความเสี่ยงของคุณเอง
bsplosion

54

จำสิ่งนี้ไว้และคุณไม่จำเป็นต้องสับสนในการแปลงวันที่และเวลาอีกครั้ง

สตริงไปยังวัตถุวันที่และเวลา = strptime

วัตถุวันที่และเวลาในรูปแบบอื่น ๆ = strftime

Jun 1 2005 1:33PM

เท่ากับ

%b %d %Y %I:%M%p

% b เดือนเป็นชื่อย่อของสถานที่ (มิถุนายน)

% d วันของเดือนในรูปของเลขทศนิยมที่ไม่มีศูนย์ (1)

% Y ปีที่มีศตวรรษเป็นตัวเลขทศนิยม (2015)

% I ชั่วโมง (นาฬิกา 12 ชั่วโมง) ในรูปแบบเลขฐานสิบศูนย์ (01)

% M นาทีเป็นตัวเลขทศนิยมที่ไม่มีซับใน (33)

% p สถานที่เกิดเหตุเทียบเท่ากับ AM หรือ PM (PM)

ดังนั้นคุณต้องมี strptime เช่นการแปลงstringเป็น

>>> dates = []
>>> dates.append('Jun 1 2005  1:33PM')
>>> dates.append('Aug 28 1999 12:00AM')
>>> from datetime import datetime
>>> for d in dates:
...     date = datetime.strptime(d, '%b %d %Y %I:%M%p')
...     print type(date)
...     print date
... 

เอาท์พุต

<type 'datetime.datetime'>
2005-06-01 13:33:00
<type 'datetime.datetime'>
1999-08-28 00:00:00

ถ้าคุณมีรูปแบบวันที่ที่แตกต่างกันคุณสามารถใช้แพนด้าหรือ dateutil.parse

>>> import dateutil
>>> dates = []
>>> dates.append('12 1 2017')
>>> dates.append('1 1 2017')
>>> dates.append('1 12 2017')
>>> dates.append('June 1 2017 1:30:00AM')
>>> [parser.parse(x) for x in dates]

เอาท์พุต

[datetime.datetime(2017, 12, 1, 0, 0), datetime.datetime(2017, 1, 1, 0, 0), datetime.datetime(2017, 1, 12, 0, 0), datetime.datetime(2017, 6, 1, 1, 30)]

% S สำหรับวินาทีเป็นทศนิยม
optimist

1
จะไม่%bแตกถ้าคุณแยกวิเคราะห์วันที่เป็นภาษาอังกฤษบนเครื่องที่ไม่มีภาษาอังกฤษหรือไม่?
bfontaine

48

ใน Python> = 3.7.0

การแปลงYYYY-MM-DD สตริงไปยังวัตถุ datetime , datetime.fromisoformatสามารถนำมาใช้

>>> from datetime import datetime

>>> date_string = "2012-12-12 10:10:10"
>>> print (datetime.fromisoformat(date_string))
>>> 2012-12-12 10:10:10

32

การประทับเวลาหลายรายการมีเขตเวลาโดยนัย เพื่อให้แน่ใจว่ารหัสของคุณจะทำงานในทุกเขตเวลาคุณควรใช้ UTC ภายในและแนบเขตเวลาทุกครั้งที่มีวัตถุแปลกปลอมเข้าสู่ระบบ

Python 3.2+:

>>> datetime.datetime.strptime(
...     "March 5, 2014, 20:13:50", "%B %d, %Y, %H:%M:%S"
... ).replace(tzinfo=datetime.timezone(datetime.timedelta(hours=-3)))

3
ทำไมคุณเก็บวิธีที่ 1 ที่น่าเกลียดและไม่ถูกต้อง ( mktime()ในช่วงการเปลี่ยนภาพ DST) ถ้าคุณรู้วิธีที่ 2 ( datetime.strptime()) หากคุณต้องการหลีกเลี่ยงข้อยกเว้นในระหว่างการกระโดดครั้งที่สอง (วิธีที่ 2 ล้มเหลว) คุณสามารถใช้calendar.timegmแทน:(datetime(1970,1,1)+timedelta(seconds=timegm(time.strptime(..)))).replace(tzinfo=timezone(timedelta(-3)))
jfs

29

ต่อไปนี้เป็นโซลูชันสองรายการที่ใช้ Pandas เพื่อแปลงวันที่ที่จัดรูปแบบเป็นสตริงเป็นวัตถุ datetime.date

import pandas as pd

dates = ['2015-12-25', '2015-12-26']

# 1) Use a list comprehension.
>>> [d.date() for d in pd.to_datetime(dates)]
[datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)]

# 2) Convert the dates to a DatetimeIndex and extract the python dates.
>>> pd.DatetimeIndex(dates).date.tolist()
[datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)]

การกำหนดเวลา

dates = pd.DatetimeIndex(start='2000-1-1', end='2010-1-1', freq='d').date.tolist()

>>> %timeit [d.date() for d in pd.to_datetime(dates)]
# 100 loops, best of 3: 3.11 ms per loop

>>> %timeit pd.DatetimeIndex(dates).date.tolist()
# 100 loops, best of 3: 6.85 ms per loop

และนี่คือวิธีแปลงตัวอย่างวันที่และเวลาดั้งเดิมของ OP:

datetimes = ['Jun 1 2005  1:33PM', 'Aug 28 1999 12:00AM']

>>> pd.to_datetime(datetimes).to_pydatetime().tolist()
[datetime.datetime(2005, 6, 1, 13, 33), 
 datetime.datetime(1999, 8, 28, 0, 0)]

มีตัวเลือกมากมายสำหรับการแปลงจากสตริงเป็น Pandas Timestamps ที่ใช้to_datetimeดังนั้นตรวจสอบเอกสารหากคุณต้องการอะไรเป็นพิเศษ

Timestamps มีคุณสมบัติและวิธีการมากมายที่สามารถเข้าถึงได้เช่นเดียวกัน.date


26

ฉันชอบโซลูชันที่ใช้parserโมดูลซึ่งเป็นคำตอบที่สองสำหรับคำถามนี้และสวยงามเพราะคุณไม่ต้องสร้างตัวอักษรสตริงใด ๆ เพื่อให้ทำงานได้ แต่หนึ่งข้อเสียคือว่ามันเป็น90% ช้าstrptimeกว่าคำตอบที่ได้รับการยอมรับด้วย

from dateutil import parser
from datetime import datetime
import timeit

def dt():
    dt = parser.parse("Jun 1 2005  1:33PM")
def strptime():
    datetime_object = datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

print(timeit.timeit(stmt=dt, number=10**5))
print(timeit.timeit(stmt=strptime, number=10**5))
>10.70296801342902
>1.3627995655316933

ตราบใดที่คุณไม่ทำอย่างนี้เป็นล้าน ๆครั้งฉันก็ยังคิดว่าparserวิธีนี้สะดวกกว่าและจะจัดการกับรูปแบบเวลาส่วนใหญ่โดยอัตโนมัติ


24

สิ่งที่ไม่ได้กล่าวถึงที่นี่และมีประโยชน์: การเพิ่มคำต่อท้ายให้กับวัน ฉันแยกตรรกะส่วนต่อท้ายเพื่อให้คุณสามารถใช้กับหมายเลขที่คุณต้องการไม่ใช่เฉพาะวันที่

import time

def num_suffix(n):
    '''
    Returns the suffix for any given int
    '''
    suf = ('th','st', 'nd', 'rd')
    n = abs(n) # wise guy
    tens = int(str(n)[-2:])
    units = n % 10
    if tens > 10 and tens < 20:
        return suf[0] # teens with 'th'
    elif units <= 3:
        return suf[units]
    else:
        return suf[0] # 'th'

def day_suffix(t):
    '''
    Returns the suffix of the given struct_time day
    '''
    return num_suffix(t.tm_mday)

# Examples
print num_suffix(123)
print num_suffix(3431)
print num_suffix(1234)
print ''
print day_suffix(time.strptime("1 Dec 00", "%d %b %y"))
print day_suffix(time.strptime("2 Nov 01", "%d %b %y"))
print day_suffix(time.strptime("3 Oct 02", "%d %b %y"))
print day_suffix(time.strptime("4 Sep 03", "%d %b %y"))
print day_suffix(time.strptime("13 Nov 90", "%d %b %y"))
print day_suffix(time.strptime("14 Oct 10", "%d %b %y"))​​​​​​​

17
In [34]: import datetime

In [35]: _now = datetime.datetime.now()

In [36]: _now
Out[36]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)

In [37]: print _now
2016-01-19 09:47:00.432000

In [38]: _parsed = datetime.datetime.strptime(str(_now),"%Y-%m-%d %H:%M:%S.%f")

In [39]: _parsed
Out[39]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)

In [40]: assert _now == _parsed

16

Django Timezone ทราบตัวอย่างวัตถุของวันที่และเวลา

import datetime
from django.utils.timezone import get_current_timezone
tz = get_current_timezone()

format = '%b %d %Y %I:%M%p'
date_object = datetime.datetime.strptime('Jun 1 2005  1:33PM', format)
date_obj = tz.localize(date_object)

การแปลงนี้สำคัญมากสำหรับ Django และ Python เมื่อคุณมีUSE_TZ = True:

RuntimeWarning: DateTimeField MyModel.created received a naive datetime (2016-03-04 00:00:00) while time zone support is active.

12

สร้างฟังก์ชั่นยูทิลิตี้ขนาดเล็กเช่น:

def date(datestr="", format="%Y-%m-%d"):
    from datetime import datetime
    if not datestr:
        return datetime.today().date()
    return datetime.strptime(datestr, format).date()

นี่มันอเนกประสงค์พอ:

  • หากคุณไม่ผ่านการขัดแย้งใด ๆ มันจะกลับวันที่วันนี้
  • มีรูปแบบวันที่เป็นค่าเริ่มต้นที่คุณสามารถแทนที่ได้
  • คุณสามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อส่งคืนวันที่และเวลา

2
formatเป็นคำที่สงวนไว้ในไพ ธ อนและไม่ควรใช้เป็นชื่อตัวแปร
ทำลาย

12

มันจะเป็นประโยชน์สำหรับการแปลงสตริงเป็นวันที่และเวลาด้วยเขตเวลา

def convert_string_to_time(date_string, timezone):
    from datetime import datetime
    import pytz
    date_time_obj = datetime.strptime(date_string[:26], '%Y-%m-%d %H:%M:%S.%f')
    date_time_obj_timezone = pytz.timezone(timezone).localize(date_time_obj)

    return date_time_obj_timezone

date = '2018-08-14 13:09:24.543953+00:00'
TIME_ZONE = 'UTC'
date_time_obj_timezone = convert_string_to_time(date, TIME_ZONE)

9

arrowมีฟังก์ชันที่มีประโยชน์มากมายสำหรับวันที่และเวลา โค้ดนี้ให้คำตอบสำหรับคำถามและแสดงว่าลูกศรสามารถจัดรูปแบบวันที่ได้อย่างง่ายดายและแสดงข้อมูลสำหรับโลแคลอื่น ๆ

>>> import arrow
>>> dateStrings = [ 'Jun 1  2005 1:33PM', 'Aug 28 1999 12:00AM' ]
>>> for dateString in dateStrings:
...     dateString
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').datetime
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').format('ddd, Do MMM YYYY HH:mm')
...     arrow.get(dateString.replace('  ',' '), 'MMM D YYYY H:mmA').humanize(locale='de')
...
'Jun 1  2005 1:33PM'
datetime.datetime(2005, 6, 1, 13, 33, tzinfo=tzutc())
'Wed, 1st Jun 2005 13:33'
'vor 11 Jahren'
'Aug 28 1999 12:00AM'
datetime.datetime(1999, 8, 28, 0, 0, tzinfo=tzutc())
'Sat, 28th Aug 1999 00:00'
'vor 17 Jahren'

ดูhttp://arrow.readthedocs.io/en/latest/สำหรับข้อมูลเพิ่มเติม



4

หากคุณต้องการรูปแบบวันที่เท่านั้นคุณสามารถแปลงรูปแบบวันที่ด้วยตนเองได้โดยผ่านฟิลด์ที่คุณต้องการเช่น:

>>> import datetime
>>> date = datetime.date(int('2017'),int('12'),int('21'))
>>> date
datetime.date(2017, 12, 21)
>>> type(date)
<type 'datetime.date'>

คุณสามารถส่งค่าสตริงที่แยกเพื่อแปลงเป็นประเภทวันที่ได้เช่น:

selected_month_rec = '2017-09-01'
date_formate = datetime.date(int(selected_month_rec.split('-')[0]),int(selected_month_rec.split('-')[1]),int(selected_month_rec.split('-')[2]))

คุณจะได้รับค่าผลลัพธ์ในรูปแบบวันที่


2

นอกจากนี้คุณยังสามารถตรวจสอบ dateparser

dateparser จัดเตรียมโมดูลเพื่อแยกวันที่แปลเป็นภาษาท้องถิ่นได้อย่างง่ายดายในเกือบทุกรูปแบบสตริงที่พบได้ทั่วไปบนหน้าเว็บ

ติดตั้ง:

$ pip install dateparser

นี่คือฉันคิดว่าวิธีที่ง่ายที่สุดที่คุณสามารถแยกวันที่

วิธีที่ตรงไปตรงมาที่สุดคือการใช้dateparser.parseฟังก์ชั่นซึ่งล้อมรอบฟังก์ชันส่วนใหญ่ในโมดูล

รหัสตัวอย่าง:

import dateparser

t1 = 'Jun 1 2005  1:33PM'
t2 = 'Aug 28 1999 12:00AM'

dt1 = dateparser.parse(t1)
dt2 = dateparser.parse(t2)

print(dt1)
print(dt2)

เอาท์พุท:

2005-06-01 13:33:00
1999-08-28 00:00:00

1

ดูคำตอบของฉัน

ในข้อมูลโลกแห่งความจริงนี่เป็นปัญหาที่แท้จริง: รูปแบบวันที่หลายรูปแบบไม่ตรงกันไม่สมบูรณ์ไม่สอดคล้องกันและหลายภาษา / ภูมิภาคมักผสมกันอย่างอิสระในชุดข้อมูลเดียว มันไม่โอเคสำหรับรหัสการผลิตที่จะล้มเหลวปล่อยให้อยู่คนเดียวยกเว้นเป็นสุขเหมือนสุนัขจิ้งจอก

เราต้องลอง ... จับหลายรูปแบบวันที่และเวลา fmt1, fmt2, ... , fmtn และระงับ / จัดการข้อยกเว้น (จากstrptime()) สำหรับทุกคนที่ไม่ตรงกัน (และโดยเฉพาะอย่างยิ่งหลีกเลี่ยงการต้องมีบันไดเยื้อง yukky n-deep .. ข้อจับ) จากทางออกของฉัน

def try_strptime(s, fmts=['%d-%b-%y','%m/%d/%Y']):
    for fmt in fmts:
        try:
            return datetime.strptime(s, fmt)
        except:
            continue

    return None # or reraise the ValueError if no format matched, if you prefer

คำถามกล่าวว่าไม่มีอะไรเกี่ยวกับ "หลายรูปแบบไม่ตรงกันไม่สมบูรณ์ไม่สอดคล้องกันและรูปแบบวันที่หลายภาษา / ภูมิภาค" ซึ่งอาจเป็นปัญหาจริง แต่ไม่เกี่ยวข้องที่นี่
RoG

1
@RoG: มันไม่เคยบอกว่าพวกเขาไม่ได้และมันก็ส่อให้เห็นว่าพวกเขาเป็น: "รายการใหญ่ ... ฐานข้อมูล" ในฐานข้อมูลส่วนใหญ่ทุกครั้ง / logfile ฉันได้ทำงาน (แม้แต่ขนาดเล็ก) มีหลายรูปแบบวันที่ตัวระบุเขตเวลา MM-DD ฯลฯ ในการผลิตมันเป็นที่ยอมรับไม่ได้ที่จะเขียนโค้ดเปราะซึ่ง hardcodes ในรูปแบบและล้มเหลวยกเว้นเมื่อ ไม่ได้รับรูปแบบที่คาดไว้ (แม้จะคืนค่า None หรือ '' ก็ยอมรับได้มากกว่า) ดังนั้นความต้องการรูปแบบที่หลากหลาย ดังนั้นนี่จะตอบคำถามที่ถามและฉันใช้เวลาในการหาวิธี Pythonic ที่สุดในการจัดการข้อผิดพลาดจากหลายรูปแบบ
smci

"ฐานข้อมูลขนาดใหญ่รายการ ... " ก็หมายความว่ามีจำนวนมากไม่ใช่ว่าเป็นรูปแบบที่แตกต่างกันทั้งหมด เป็นที่ยอมรับได้อย่างสมบูรณ์ในการเขียนโค้ดที่อ่านรูปแบบเดียวหากคุณรู้ว่ามีรูปแบบเดียวในอินพุต ในกรณีนี้มันควรจะผิดพลาดถ้ามันผ่านสิ่งที่ไม่ได้อยู่ในรูปแบบที่เหมาะสม
RoG

@RoG: มันเป็นที่ยอมรับไม่ได้ที่จะเขียนรหัสการผลิตซึ่งผิดพลาดในรูปแบบที่ผิด / Unicode / ตัดทอน / หายไป / ข้อมูล NaNs, M / D / Y เทียบกับรูปแบบ D / M / Y, YY กับ YYYY ฯลฯ โดยเฉพาะอย่างยิ่ง ข้อยกเว้นสามารถหลีกเลี่ยงได้ด้วยโซลูชันเจ็ดซับตามที่ฉันแสดง "ฐานข้อมูลขนาดใหญ่" ในโลกแห่งความเป็นจริงส่วนใหญ่นั้นเป็นเช่นนั้น เพียงเพราะ OP ไม่ได้พูดอย่างชัดเจนนั่นไม่ได้หมายความว่ามันไม่ใช่บริบททั่วไป ฉันจะไม่ไปทะเลาะกับคุณ คุณใช้ชุดข้อมูลประเภทใดและทำไมคุณคิดว่าสมมติฐานเหล่านั้นสมเหตุสมผล ยกเว้นว่าเรากำลังพูดถึงรหัสของเล่นที่ต้องมีการแทรกแซงอย่างต่อเนื่อง
smci

1
ดูเหมือนว่าโง่เล็กน้อยที่จะคิดด้วยความมั่นใจว่า OP จะต้องมีข้อมูลที่ไม่เคยมีมาก่อน ใช่เป็นไปได้ที่จะมีข้อมูลเช่นนั้น แต่เราไม่สามารถสรุปได้ว่าเป็นกรณีนี้ ฉันคิดว่าคำตอบนี้มีประโยชน์แน่นอนสำหรับฉันที่ค้นหาคำตอบที่คล้ายกันกับคำถามที่คล้ายกันมากซึ่งความไม่สอดคล้องกันเป็นปัญหาอย่างแน่นอน
พอลมิลเลอร์

1
emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv")
emp.info()

จะแสดงคอลัมน์ "วันที่เริ่มต้น" และ "เวลาเข้าสู่ระบบล่าสุด" ทั้งคู่คือ "object = strings" ใน data-frame

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 8 columns):
First Name           933 non-null object
Gender               855 non-null object
Start Date           1000 non-null object

Last Login Time      1000 non-null object
Salary               1000 non-null int64
Bonus %              1000 non-null float64
Senior Management    933 non-null object
Team                 957 non-null object
dtypes: float64(1), int64(1), object(6)
memory usage: 62.6+ KB

โดยใช้parse_datesตัวเลือกในการread_csvกล่าวถึงคุณสามารถแปลงวันที่และเวลาสตริงของคุณในรูปแบบวันที่และเวลาแพนด้า

emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv", parse_dates=["Start Date", "Last Login Time"])
emp.info()


<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 8 columns):
First Name           933 non-null object
Gender               855 non-null object
Start Date           1000 non-null datetime64[ns]
Last Login Time      1000 non-null datetime64[ns]
Salary               1000 non-null int64
Bonus %              1000 non-null float64
Senior Management    933 non-null object
Team                 957 non-null object
dtypes: datetime64[ns](2), float64(1), int64(1), object(4)
memory usage: 62.6+ KB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.