Python 将日期从可读字符串转换为更标准的字符串

Python 将日期从可读字符串转换为更标准的字符串,python,regex,replace,Python,Regex,Replace,我的日期格式是8月27日星期五,这在编程上是一场噩梦,我相信你可以想象得到 我想知道如何最好地将这些转换为美国日期格式08/27/13。我需要指定从月份开始的年份,即8月至12月暗示13,以及1月至7月暗示14 我在考虑如何在regex中实现这一点,甚至只是做一系列的字符串替换 但复杂的是我有一个字符串列表,不是所有的字符串都是这种形式的日期。如果其他人里面有数字,我如何测试此表单的日期,如果是,如何替换 e、 g list=[“非日期”、“也非日期”、“1月5日星期三”、“此处无日期”] 测试

我的日期格式是8月27日星期五,这在编程上是一场噩梦,我相信你可以想象得到

我想知道如何最好地将这些转换为美国日期格式
08/27/13
。我需要指定从月份开始的年份,即8月至12月暗示
13
,以及1月至7月暗示
14

我在考虑如何在regex中实现这一点,甚至只是做一系列的字符串替换

但复杂的是我有一个字符串列表,不是所有的字符串都是这种形式的日期。如果其他人里面有数字,我如何测试此表单的日期,如果是,如何替换

e、 g

list=[“非日期”、“也非日期”、“1月5日星期三”、“此处无日期”]

测试的要求使得regex看起来很合适,但是我读了很多关于在Python中使用
re
的文章,尽管我不知道为什么。我是否应该(学习足够多的知识)使用它

有了@Allan的回答,我就可以解决我的问题了:

def is_date(string):
    tmp = string.replace('th','')
    string = tmp.replace('rd','')
    tmp = string.replace('nd','')
    string = tmp.replace('st','')
    try:
        d = strptime(string, "%a %d %b")
        date = str(d[1]) + "/" + str(d[2]) + "/"
        if d[1] >= 8:
            date += "13"
        else:
            date += "14"
        return date
    except ValueError:
        return 0
感谢您的回答,@Allan、@adsmith和@Codnoder。

看看。它会引发
ValueError
,因此您可能希望捕获该异常并忽略非日期字符串

在这种情况下,我会避免使用正则表达式,因为日期格式可能会变得非常复杂。您需要指定可能的月份和工作日缩写,检查大小写变化。。。如果你只需要解决一个简单且定义明确的问题,你真的,真的不想去那里:)

@奥利福德:改进你的新代码,我得出:

import datetime

def is_date(string):
    for suffix in ("th", "rd", "nd", "st"):
        string = string.replace(suffix, "")

    try:
        d = datetime.datetime.strptime(string, "%a %d %b")
        y = 2014
        if d.month >= 8:
            y = 2013            
        d = d.replace(year = y)
        return d.strftime("%x")
    except ValueError:
        return None
它使用datetime类中的函数来避免手动操作。请注意,在转换为字符串时使用了
%x
:它将使用当前区域设置来格式化日期。这可能是你想要的,也可能不是


我还要看看@Marian提到的
Dateutil.parser
。如果您不关心添加外部依赖项,那么它似乎也可以解决这个问题,也许更容易解决(尽管我没有尝试过)。

Dateutil.parser将为您完成这项工作,并为您提供更多帮助:


对于这个特定任务来说,正则表达式似乎不是最糟糕的主意。下面是一个很长的例子。我相信有很多更有效的方法

import re

# Convert dates like "Fri 27th Aug" with year fudge
mons = {
    'Aug' : ( 8, 13),
    'Sep' : ( 9, 13),
    'Oct' : (10, 13),
    'Nov' : (11, 13),
    'Dec' : (12, 13),
    'Jan' : ( 1, 14),
    'Feb' : ( 2, 14),
    'Mar' : ( 3, 14),
    'Apr' : ( 4, 14),
    'May' : ( 5, 14),
    'Jun' : ( 6, 14),
    'Jul' : ( 7, 14),
}
days = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')

# pattern is purposefully strict to avoid false matches against
# other arbitrary strings
pat = re.compile(r'^(%s) (\d+)(st|nd|rd|th) (%s)$' %
                 ('|'.join(days), '|'.join(mons.keys())))
strlist = ['not a date', 'als0 not a dat3', 'Wed 5th Jan', 'no date here']
newlist = []
for tok in strlist:
    m = re.match(pat, tok)
    if m:
        day = int(m.group(2))
        mon = m.group(4)
        newlist.append('%02d/%02d/%02d' % (mons[mon][0], day,mons[mon][1]))
    else:
        newlist.append(tok)

for tok in newlist:
    print tok

编辑:更改了日期格式以匹配操作更正。

strtime
对于像
27th
这样的序数将有相当大的困难。这是真的。。。也许预处理列表会有帮助。。。如果不可能,我将使用格式字符串的三种变体:“%a%b%dth”、“a%b%dnd”、“a%b%dst”。当然,这假设这是列表中表示日期的唯一格式。如果有更多,事情无论如何都会变得非常困难:“日期格式[sic]”不能“变得非常复杂”,因为只有一种已知的格式。我在这一点上支持@Allan。使用正则表达式对于看起来相当简单的脚本来说过于复杂。我会完全按照他的建议去做,然后尝试strtime,如果它抛出一个
ValueError
,然后尝试下一个序数,如果它抛出一个ValueError,然后尝试下一个序数,然后传递它,除了。@OllieFord如果只有一种格式,那么从该格式预处理并通过strtime运行它。我可以编辑艾伦的答案,如果他自己不想这么做的话,给他一个很好的方法。实际上,以前的“Wed 5th Jan”风格是正确的。我已经相应地编辑了您的答案-但我对正则表达式并不完全熟悉,所以如果有错误,请更正。一旦确认,我将接受。不过,我喜欢这个解决方案-
mons
dict是一种比我一起破解的更简洁的获取月份和年份的方法。我正在尝试将
re
应用到另外两个函数中。为什么
\d+[:]\d+
不匹配形式
21:20
的时间?它可能匹配,尽管冒号周围的方括号是不必要的,并且括号中没有匹配的
\d+
,因此它们不会被捕获。另外,请查找
re.search()
re.match()
之间的差异,因为它会根据您搜索的内容产生差异。也许可以提交另一个问题,详细说明这个新问题?最好的。