Python:使用格式化将字符串解析为日期

时间:2015-08-13 18:28:04

标签: python regex date

用户可以输入字符串,字符串包含以下格式MM/DD/YYMM/DD/YYYY的日期。有没有一种有效的方法从字符串中提取日期?我在考虑使用RegEx for \d+\/\d+\/\d+。我还希望能够对日期进行排序。即如果字符串包含8/17/1508/16/2015,则会先列出8/16日期,然后再列出8/17

6 个答案:

答案 0 :(得分:3)

你也可以尝试strptime:

import time

dates = ('08/17/15', '8/16/2015')

for date in dates:
    print(date)
    ret = None
    try:
        ret = time.strptime(date, "%m/%d/%Y")
    except ValueError:
        ret = time.strptime(date, "%m/%d/%y")
    print(ret)

<强>更新

评论后

更新:

这样,如果无法解析日期,您将获得有效的日期或None

import time

dates = ('08/17/15', '8/16/2015', '02/31/15')

for date in dates:
    print(date)
    ret = None
    try:
        ret = time.strptime(date, "%m/%d/%Y")
    except ValueError:
        try:
            ret = time.strptime(date, "%m/%d/%y")
        except ValueError:
            pass
    print(ret)

更新 2

在有关要求的评论之后再发布一次更新。

这是一个版本(它只处理日期;而不是之前/之后的文本。但是使用正则表达式组可以很容易地提取它):

import re
import time

dates = ('foo 1 08/17/15', '8/16/2015 bar 2', 'foo 3 02/31/15 bar 4')

for date in dates:
    print(date)
    match = re.search('(?P<date>[0-9]+/[0-9]+/[0-9]+)', date)
    date_str = match.group('date')
    ret = None
    try:
        ret = time.strptime(date_str, "%m/%d/%Y")
    except ValueError:
        try:
            ret = time.strptime(date_str, "%m/%d/%y")
        except ValueError:
            pass
    print(ret)

答案 1 :(得分:3)

查看datetime.strptime,它是一个内置函数,知道如何从字符串创建日期时间对象。它接受要转换的字符串,并写入format日期。

from datetime import datetime

def str_to_date(string):
    pattern = '%m/%d/%Y' if len(string) > 8 else '%m/%d/%y'
    try:
        return datetime.strptime(string, pattern).date()
    except ValueError:
        raise  # TODO: handle invalid input

该函数返回一个date()对象,可以直接与其他date()个对象进行比较(例如排序时)。

用法:

>>> d1 = str_to_date('08/13/2015')
>>> d2 = str_to_date('08/12/15')
>>> d1
datetime.date(2015, 8, 13)
>>> d2
datetime.date(2015, 8, 12)
>>> d1 > d2
True

更新

OP在评论中解释说,不应该自动丢弃诸如'foo 08/13/2015 bar'之类的字符串,并且应该从中提取日期。

要实现这一点,我们必须首先在用户的输入中搜索候选字符串:

import re
from datetime import date

user_string = input('Enter something')  # use raw_input() in Python 2.x

pattern = re.compile(r'(\d{2})/(\d{2})/(\d{4}|\d{2})')  # 4 digits match first!
match = re.search(pattern, user_string)

if not match:
    d = None
else:
    month, day, year = map(int, match.groups())
    try:
        d = date(year, month, day)
    except ValueError:
        d = None  # or handle error in a different way

print(d)

代码读取用户输入,然后尝试在其中查找表示MM/DD/YYYYMM/DD/YY格式的日期的模式。请注意,最后一个捕获组(在括号中,即())检查四个或两个连续数字。

如果找到候选日期,它会解压缩匹配中的捕获组,同时将它们转换为整数。然后,它使用三个匹配的部分尝试创建新的date()对象。如果失败,则候选日期无效,例如'02/31/2015'

脚注:

  • 代码只会捕获输入中的第一个候选日期
  • 所使用的正则表达式,在其当前形式中,也会匹配输入中的日期,例如&#39; 12308/13 / 2015123&#39;。如果这不可取,则必须进行修改,可能会添加一些前瞻/后瞻断言。

答案 2 :(得分:1)

为什么不使用strptime将它们存储为datetime个对象。这些对象可以很容易地进行比较和排序。

import datetime
try:
    date = datetime.datetime.strptime("08/03/2015", "%m/%d/%Y")
except:
    date = datetime.datetime.strptime("08/04/15", "%m/%d/%y")
finally:
    dateList.append(date)

请注意%Y%y之间的区别。然后,您可以只比较以这种方式生成的日期,以查看哪些日期更大或更小。您也可以使用dateList.sort()

对其进行排序

如果您希望再次将日期作为字符串,则可以使用:

>>> dateString = date.strftime("%Y-%m-%d")
>>> print dateString
'2015-08-03'

答案 3 :(得分:0)

如果可以使用datetime.strptime,为什么还要使用正则表达式?

答案 4 :(得分:0)

您可以使用Pandas的日期parser

import pandas as pd

timestr = ['8/8/95', '8/15/2014']
>>> [pd.datetools.parse(d) for d in timestr]
[datetime.datetime(1995, 8, 8, 0, 0), datetime.datetime(2014, 8, 15, 0, 0)]

答案 5 :(得分:0)

使用正则表达式组,我们得到类似的结果:

import re
ddate = '08/16/2015'

reg = re.compile('(\d+)\/(\d+)\/(\d+)')
matching = reg.match(ddate)
if matching is not None:
    print(matching.groups())

会产生

('08','16','2015')

之后你可以解析这个,但是如果你想从第一个地方摆脱领先的0,你可以使用

reg = re.compile('0*(\d+)\/0*(\d+)\/(\d+)')