2009-11-20 61 views
3

我在嘗試對CSV文件進行排序,並且希望按相反順序按日期排序項目:newest first。在Python中按日期排序CSV

def SortCsvByField(filename, fieldNo, sep = ','): 
    records = [line.split(sep) for line in file(filename)] 

只要這很容易,但我如何比較日期?

+0

這取決於日期格式 – SilentGhost 2009-11-20 23:49:33

回答

5

我建議安裝優秀的dateutil模塊。 (在Ubuntu/Debian中,它是由python-dateutil包提供的)。

dateutil可以解析日期字符串到datetime對象:它可以處理許多不同的日期格式,您無需動一根手指(*):

import dateutil.parser as dparser 
date=dparser.parse("Mon May 7 1883 10:36:28") 
print(date) 
# 1883-05-07 10:36:28 

date=dparser.parse("1685-3-21") 
print(date) 
# 1685-03-21 00:00:00 

date=dparser.parse("12/17/1770") 
print(date) 
# 1770-12-17 00:00:00 

注意,解析被訓釋「1770年12月17日」形式爲「MM/DD/YYYY」。您可以使用解析的dayfirstyearfirst選項更改此行爲。 (見http://labix.org/python-dateutil

print(type(date)) 
# <type 'datetime.datetime'> 

datetime對象可以很容易地進行排序:

dates=[dparser.parse("Mon May 7 1883 10:36:28"),dparser.parse("1685-3-21"),dparser.parse("12/17/1770"),] 
dates.sort() 
print(dates) 
# [datetime.date(1685, 3, 21), datetime.date(1770, 12, 17), datetime.date(1833, 5, 7)] 

如果您不想安裝dateutil包,那麼你就必須 推出自己的轉換日期字符串的方法到日期時間對象中。這需要更多的工作,因爲您必須定義格式。在下面,'%Y-%m-%d'定義了YYYY-MM-DD格式。有關可用格式代碼的更多信息,請參見http://au2.php.net/strftime(或strftime的手冊頁)。

例如,

dates=[datetime.datetime.strptime(date_str,'%Y-%m-%d') for date_str in 
     ('1883-5-7','1685-3-21','1770-12-17',)] 
print([str(date) for date in dates]) 
# ['1883-05-07 00:00:00', '1685-03-21 00:00:00', '1770-12-17 00:00:00'] 
dates.sort() 
print([str(date) for date in dates]) 
# ['1685-03-21 00:00:00', '1770-12-17 00:00:00', '1883-05-07 00:00:00'] 

要控制格式轉換時datetime對象返回到可打印的字符串,可以使用datetime.datetime.strftime()方法。

+0

(1)「如果你使用的是Linux 「??有關於dateutil的平臺依賴嗎?它似乎在Windows上正常工作[但參見下面的第3點](2)日期前面有'#'例如'#2009-09-25 10:36:28'?從print()輸出?如果是這樣,他們是錯的。應該是例如(3)對於那些堅持「DD/MM/YYYY」公約的人來說,它將把'01/02/2009''解釋爲二月的第一天,手指,會嗎?它不會像12月31日那樣默默地採取「31/12/2008」''而在1月2日也採取'01/02/2009''是否會令人討厭? – 2009-11-21 09:16:44

+0

這是一個很好的開始,但是你沒有解決它默認情況下接受混合dd/mm和mm/dd日期的問題(AFAICT)無法選擇「嚴格」行爲。 – 2009-11-21 21:01:20

+1

我不明白爲什麼它默認追加10-19到'月份,日期'的日期。例如1946 - > 1946-10-19和46 - > 2046-10-19 ..我們可以更改默認行爲嗎? – ThinkCode 2010-10-19 19:13:25

2

如果您的日期採用ISO-8601格式(YYYY-MM-DD),那麼您可以將它們排序爲字符串,否則您必須先解析它們(datetime.strptime)。

然後,您可以使用例如sorted(records, key=lambda a:a[1])進行排序,如果日期是第二個字段。

2

假設你知道的日期格式,以及他們在您的CSV文件的第1列:

>>> import csv 
>>> from datetime import datetime 
>>> def date_key(row): 
     return datetime.strptime(row[1].strip(), "%m/%d/%Y") 

>>> with open('c:\\temp\\test\\date_test.csv', 'rb') as f: 
     data = list(csv.reader(f)) 

>>> data 
[['foo', ' 3/11/2004'], ['bar', ' 2/15/2001'], ['baz', '11/15/2007'], ['bat', '10/13/2002']] 
>>> data.sort(key=date_key) 
>>> data 
[['bar', ' 2/15/2001'], ['bat', '10/13/2002'], ['foo', ' 3/11/2004'], ['baz', '11/15/2007']]