Python does not specify a date string handling class
- 2020-04-02 13:42:53
- OfStack
I analyzed the features of time format such as 19920203, 199203, 1992.02.03, 1992.02, 1992-02-03, 1992-02, 920203, and listed the regular expressions as follows:
^((?:19|20)?d{2})[-.]?((?:[0-1]?|1)[0-9])[-.]?((?:[0-3]?|[1-3])[0-9])?$
Of course, this expression is not perfect, it can only do simple cutting, can't judge the validity of the date, about whether the date is legal, I still leave Python time function to deal with it.
According to the above regular expression, the DateParser class I wrote is as follows:
import re
import datetime
# ***************************************************
# *
# * Description: Non-standard date string handling
# * Author: wangye <pcn88 at hotmail dot com>
# *
# ***************************************************
class DateParser(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.month if flags[1] else 1
d = date.day if flags[2] else 1
return datetime.date(y, m, d)
def __mergeFlags(self, flags1, flags2):
l = []
length = min(len(flags1), len(flags2))
for i in range(0, length):
if flags1[i] and flags2[i]:
l.append(True)
else:
l.append(False)
return l
def parse(self, strdate):
"""
Description: time resolution method.
Parameters: strdate The time string to analyze, such as the target time type datetime(1992, 2, 3)
One of the following strings can be parsed:
19920203
199203
1992.02.03
1992.02
1992-02-03
1992-02
920203
The return value:
If successful
tuples (datetime, flags) , including datetime Represents the legal time of completion of the transformation,
flags It's the flag bit, it's the significant bit, for example 199202 Actually converted year and month, day not,
But this function returns by default 1 Day, but flags Will be represented as (True, True, False),
The previous two True The year and the month are converted, respectively, and the last one False The date is not converted.
If it fails
return None .
"""
m = self.pattern.match(strdate)
flags = [False, False, False]
if m:
matches = list(m.groups())
flags = list(map(lambda x:True if x!=None else False, matches))
results = list(map(lambda x:int(x) if x!=None else 1, matches))
# results = list(map(lambda x:1 if x==None else x, results))
if results[0]<100:
if results[0]>9:
results[0] += 1900
else:
results[0] += 2000
return (datetime.date(results[0], results[1], results[2]), flags)
else:
return None
def convert(self, strdate, format):
"""
Description: convert date to specified format.
Parameters: strdate with parse methods strdate Parameters.
format Python Time format identification, same datetime.date.strftime Format the identity.
The return value:
If successful, returns the specified format Format of the time string.
If it fails, return None .
"""
date = self.parse(strdate)
if date:
date = date[0]
return datetime.date.strftime(date, format)
else:
return None
def compare(self, strdate1, strdate2):
"""
Description: compare two dates.
Parameters: strdate1 and strdate2 with parse methods strdate parameter
The return value:
It could be one of the following values
-4 strdate1 invalid , strdate2 effective
-3 strdate1 effective , strdate2 invalid
-2 strdate1 and strdate2 invalid
-1 strdate1 < strdate2
0 strdate1 = strdate2
1 strdate1 > strdate2
"""
date1,flags1 = self.parse(strdate1)
date2,flags2 = self.parse(strdate2)
if date1 == None and date2 != None:
return -4
if date1 != None and date2 == None:
return -3
elif date1 == None and date2 == None:
return -2
flags = self.__mergeFlags(flags1, flags2)
date1 = self.__cutDate(date1, flags)
date2 = self.__cutDate(date2, flags)
if date1>date2:
return 1
elif date1<date2:
return -1
else:
return 0
Here are some examples for your reference:
>>> 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