Python不规范的日期字符串处理类
我分析了形如19920203、199203、1992.02.03、1992.02、1992-02-03、1992-02、920203时间格式特征,列出了正则表达式如下:
^((?:19|20)?\d{2})[-.]?((?:[0-1]?|1)[0-9])[-.]?((?:[0-3]?|[1-3])[0-9])?$当然这个表达式还不是很完善,只能做简单的切割,不能判断日期的合法性,关于日期是否合法,我还是交给Python的时间功能来处理吧。
根据上面的正则表达式,我写的DateParser类如下:
importre
importdatetime
#***************************************************
#*
#*Description:非标准的日期字符串处理
#*Author:wangye <pcn88athotmaildotcom>
#*
#***************************************************
classDateParser(object):
def__init__(self):
self.pattern=re.compile(
r'^((?:19|20)?\d{2})[-.]?((?:[0-1]?|1)[0-9])[-.]?((?:[0-3]?|[1-3])[0-9])?$'
)
def__cutDate(self,date,flags):
y=date.year
m=date.monthifflags[1]else1
d=date.dayifflags[2]else1
returndatetime.date(y,m,d)
def__mergeFlags(self,flags1,flags2):
l=[]
length=min(len(flags1),len(flags2))
foriinrange(0,length):
ifflags1[i]andflags2[i]:
l.append(True)
else:
l.append(False)
returnl
defparse(self,strdate):
"""
描述:时间解析方法。
参数:strdate要分析的时间字符串,比如目标时间类型datetime(1992,2,3)
可以被解析的是下述字符串之一:
19920203
199203
1992.02.03
1992.02
1992-02-03
1992-02
920203
返回值:
如果成功
元组(datetime,flags),其中datetime表示转换完成的合法时间,
flags是标志位,表示有效位数,比如199202实际转换了年和月,日没有,
但是本函数将默认返回1日,但是flags将表示为(True,True,False),
前面两个True分别表示年和月被转换,最后一个False表示日没有被转换。
如果失败
返回None。
"""
m=self.pattern.match(strdate)
flags=[False,False,False]
ifm:
matches=list(m.groups())
flags=list(map(lambdax:Trueifx!=NoneelseFalse,matches))
results=list(map(lambdax:int(x)ifx!=Noneelse1,matches))
#results=list(map(lambdax:1ifx==Noneelsex,results))
ifresults[0]<100:
ifresults[0]>9:
results[0]+=1900
else:
results[0]+=2000
return(datetime.date(results[0],results[1],results[2]),flags)
else:
returnNone
defconvert(self,strdate,format):
"""
描述:转换日期为指定格式。
参数:strdate同parse方法的strdate参数。
formatPython时间格式标识,同datetime.date.strftime格式化标识。
返回值:
如果成功,返回指定format格式的时间字符串。
如果失败,返回None。
"""
date=self.parse(strdate)
ifdate:
date=date[0]
returndatetime.date.strftime(date,format)
else:
returnNone
defcompare(self,strdate1,strdate2):
"""
描述:比较两个日期。
参数:strdate1和strdate2同parse方法的strdate参数
返回值:
可以是下列值之一
-4 strdate1无效, strdate2有效
-3 strdate1有效, strdate2无效
-2 strdate1和strdate2无效
-1 strdate1<strdate2
0 strdate1=strdate2
1 strdate1>strdate2
"""
date1,flags1=self.parse(strdate1)
date2,flags2=self.parse(strdate2)
ifdate1==Noneanddate2!=None:
return-4
ifdate1!=Noneanddate2==None:
return-3
elifdate1==Noneanddate2==None:
return-2
flags=self.__mergeFlags(flags1,flags2)
date1=self.__cutDate(date1,flags)
date2=self.__cutDate(date2,flags)
ifdate1>date2:
return1
elifdate1<date2:
return-1
else:
return0
下面举几个例子供大家参考:
>>>DateParser().parse("19860126")
(datetime.date(1986,1,26),[True,True,True])
>>>DateParser().parse("199111")
(datetime.date(1991,11,1),[True,True,False])
>>>DateParser().parse("1991")
(datetime.date(1919,9,1),[True,True,True])
>>>DateParser().parse("8511")
(datetime.date(1985,11,1),[True,True,False])
>>>DateParser().convert("19911101","%Y*%m*%d")
'1991*11*01'
>>>DateParser().convert("1990.1.01","%Y.%m.%d")
'1990.01.01'
>>>DateParser().compare("1992.2","19922")
0
>>>DateParser().compare("1992.2","1956.03.1")
1