Python 解析CSV文件时遇到问题,无法解析日期
我使用的是Python 解析CSV文件时遇到问题,无法解析日期,python,csv,Python,Csv,我使用的是dateutil.parser.parse(date),它可以很好地处理单个日期,但问题是如果我有两天(即20/04/2032和05/04/1991),那么它将分别读取为4月20日和5月4日 我将在形式一致的专栏中阅读,但我不会提前知道专栏的形式,因为我希望从多个来源支持CSV 假设我有一个这样的列表(尽管实际上它们可能更大): [“01/02/2012”、“01/04/2012”、“01/05/2012”、“01/05/2012”、“01/25/2012”] [“01022012”、
dateutil.parser.parse(date)
,它可以很好地处理单个日期,但问题是如果我有两天(即20/04/2032
和05/04/1991
),那么它将分别读取为4月20日和5月4日
我将在形式一致的专栏中阅读,但我不会提前知道专栏的形式,因为我希望从多个来源支持CSV
假设我有一个这样的列表(尽管实际上它们可能更大):
[“01/02/2012”、“01/04/2012”、“01/05/2012”、“01/05/2012”、“01/25/2012”]
[“01022012”、“01042012”、“01052012”、“01052012”、“01252012”]
[“01/2nd/2012”等]
01
是月份,但我需要自动检查。我不能只检查大于12的数字,因为它可能意外地捕获年份子字符串
我需要从中提取的数据是该月的前一天还是后一天。因此,当我稍后返回并再次解析字符串时,我知道要获取什么
我似乎想不出一种干净有效的方法来执行此检查。如果您不知道格式,则无法解析。其实很简单。这两个(5/4/91
和5/4/1991
)都将通过任何检查有效日期的检查;但是只有你知道它是5月4日还是4月5日,你也只能知道它的格式是什么
最后,您最好希望的是一个有效的可解析日期列表,一个未解析(但可能是有效的)日期列表。然后,您必须手动检查这两个日期,以查看日期是否有意义
要获取这些列表,请执行以下操作:
try:
maybe_valid.append(dateutil.parser.parse(some_date))
except ValueError:
probably_invalid.append(some_date)
这是我提出的一个可能的路线图,看起来很合理?有任何重大缺陷或直接缺点吗?我需要一些帮助,将它转换成相对健壮的东西,因为它的目的是用于未知字符串
然后我可以用{0,1,2}为年、月、日保留一个集合,然后返回给定元素(年、月、日)不可能的位置,并使用集合减法。如果任何集合到达{},则无法读取。如果任何一个集合的末尾有超过1个元素,我会根据优先级对日期/月份进行局部选择(任何一个集合都可能假设较低的方差为月份?)。如果只有一种组合,我会在以后读取日期时存储它,并将其传递给读者。我一直在尝试解决一些问题,但我不能只搜索特定的内容,因为日期可能完全是文本。日期中甚至可能没有分隔符,像122712这样的日期可能错误地表示该日期在该月之前和之后。您想如何解析1991年4月5日?如果您没有给出格式,有两种解析方法——4月5日或5月4日。您想如何解析010101?您必须为日期定义输入格式,或者必须定义优先级规则问题是我需要统一解析,但我不知道将遇到的文件格式。文件可以是MMDDYYYY或DDMMYYY或上述任何类型。它们中的任何一个都可能是amgibious的,所以我必须在解析它之前弄清楚它的格式是什么(或者如果有一种简单的方法可以随时检查的话)。问题是我不知道如何从datetime对象转换为“这就是它的显示方式”。是否保证列中的所有日期都具有相同的格式?如果你有希望(如果一个2位数的位置的值大于12->这是一天的位置),如果每一行都可以是不同的格式,你就被套住了。可以公平地假设列是一致的,但它可能不是整数(即“二十五”或“二十五”)因此,我不知道如何检查。我不太担心过于模糊的情况,即列中的每个日期都不明确。但是让我们假设我有1000个日期,999个是不明确的,但有一个显然是第一个日期。我怎样才能以干净高效的方式发现订单不含糊(以及它是什么)?你说的“先有日期”是什么意思?对不起,我指的是“先有日期”。和月前一天一样。最简单的检查是看前两位数是否大于12。同意Burhan的说法,你必须知道它的格式。无论是DD/MM/YYYY还是MM-DD-YY,你都必须知道这一点。如果它使用更多不同的格式(都是已知的),那么没有一行解决方案,可能需要一些变通方法才能使其工作。这有一个缺点,即不使用解析器,但优点是允许我知道各种元素位于哪个位置。我不确定这种方法对我的覆盖程度有多合理。
# date is a string from the csv file.
if len(date) == 8 and all(isdigit(i) for i in date):
# then it's either the year comes first or last
date = ["-".join([date[0:4], date[4:6], date[6:8])],
"-".join([date[0:2], date[2:4], date[4:8])]
]
# only one should be a possible date. if both are and the month
# combinations don't sort it out then it's too ambigious anyway.
# I'll do something similar for a string of 6 digits. but now I know that all
# strings that are digits only are now seperated.
# I'll also figure out which is the year (or make a reasonable guess and expand
# the number to 8 and make the spaces).
date = date.lower() # or an equivalent if it screws with symbols and numbers
for month in full_length_month_list:
if month in date:
# I know I can parse this.
for month in three_letter_month_list:
if month in date:
# I know I can parse this.
month_days = {'first':01, 'second':02, 'third':03, ... ,'thirty first': 31}
for string, number in month_days:
date.replace(string,number)
for shorthand in ['st','nd','rd','th']:
date.replace(shorthand, '')
date.replace('the','')
# Then I use a regex matcher to get 3 sets of digits: The longest set is the
# year. The shortest two sets are either date or month. I can get the order
# based on the matcher. Then I can figure out by looping through if there is
# ever a date greater than 12. If so I know the order. I can also possibly
# track the replacements maybe. So that if jan/january was in the original
# string I already know anyway.