发布
社区首页 >问答首页 >从数字串中解释日期

从数字串中解释日期
EN

Code Review用户
提问于 2019-10-08 09:08:46
回答 1查看 266关注 0票数 7

我开发了一个函数,从给定的数字序列中提取日期并重新格式化它。

这是代码:

代码语言:javascript
代码运行次数:0
复制
from datetime import datetime as dt


def format_dates(field):
    n = len(field)
    match = False
    i = 0
    while match is False:
        try:
            # Take the last four digits
            year = int(field[-4 - i:n - i])
        except ValueError:
            return ''

        # Check if this year is between today's year +/- (15, 100)
        if (1919 <= year <= 2019):
            # Check if there are other 4 digits before these 4 ones
            if (len(field[-8 - i:n - i]) == 8):
                try:
                    f_date = dt.strptime(field[-8 - i:n - i],
                                         '%d%m%Y').strftime('%d/%m/%Y')
                    match = True
                    return f_date
                except ValueError:
                    pass
            else:
                return ''
        i += 1

解释:

这一职能:

  • 接受一个数字序列作为输入。
  • 从这个序列中提取最后四个数字。
  • 检查提取的四位数是否在2019年至1919年之间,如果没有,则会中断。
  • 如果是,它会检查在先前提取的数字之前是否还有4位数字,如果没有,则会中断。
  • 如果是,则尝试格式化整个8位数字。
  • 如果有ValueError异常,它就会通过(ValueError,表示有8位数字,最后4位代表一个正确的年份,但前四位数字是错的。因此,它传递到增量i+1,以添加前面的下一个数字,并删除处理序列中的最后一个数字)。

示例:

输入:‘1303201949’

  1. 迭代1:
    • I= 0,match = False
    • 年份=1946年
    • 测试1(2019年至1919年之间的年份):及格。
    • test2 (1946年之前还有4位数字,即0320位):passes。
    • 格式化整个8位数: ValueError异常,因此i= i+1并传递到下一次迭代。

  2. 迭代2:
    • I= 1,match = False
    • 年份= 0194
    • 测试1( 2019至1919年之间的年份):失败,因此i=i+1并传递到下一次迭代。

  3. 迭代3:
    • I= 2,match = False
    • 年份=2019年
    • 测试1:通过
    • 测试2:通过
    • 格式化全部8位数字(13032019):13/03/2019年(无ValueError异常)通过
    • match = True,返回格式化日期,从while循环中中断。

这个函数工作得很好,但是它处理错误的方式看起来很难看。另外,我认为它不是优化的(同样的例外是重复的,很多返回和代码似乎不优雅)。

如何重新格式化代码并使其更加优化?

EN

回答 1

Code Review用户

回答已采纳

发布于 2019-10-08 10:36:14

异常

如果算法找不到日期,则引发异常比返回''更容易。如果此函数的用户不测试该哨兵值,则返回前哨值而不是异常会导致意外行为。

注释

评论应该解释你为什么做某事,而不是怎么做。# Take the last four digits只告诉您代码本身。我宁愿在field[-4 - i:n - i]上评论为什么您做n - i而不是只做-i

嵌套

与其嵌套许多if-子句,不如测试条件和continue的负值,这样代码的其余部分就更少嵌套了。

匹配

不要测试condition is True。只要做condition。在Python中,许多值可以在测试中充当TrueFalse

无论如何,您的match从未被使用过;当您将其设置为True时,您还将返回结果,因此while True:在这里就足够了。

field

这是一个非常不清楚的变量名。此方法不包含字符串格式的日期,那么为什么不这样调用参数呢?

返回类型

你的代码现在做了两件事。它在字符串中查找日期,并将该日期转换为其他格式。最好将这两件事分开,然后返回一个datetime.datetime,让这个方法的调用者担心如何正确格式化。

while True

您使用的是带有递增计数器的while True-loop。更好的方法是使用for i in range(...)或使用itertools.countfor i in itertools.count()。在这种情况下,您知道只会有len(field) - 7迭代,所以您最好使用它。

还原算法

您将显式测试子字符串是否有8个字符长,然后测试其格式是否正确。通过将while True更改为for-loop,您知道子字符串将有8个字符长。然后,首先尝试将其转换为datetime,然后检查年份是否正确,这是有意义的:

代码语言:javascript
代码运行次数:0
复制
def format_dates2(date_string):
    n = len(date_string)
    for i in range(n - 7):
        sub_string = date_string[-(8 + i) : n - i]
        # not just -i because that fails at i==0
        try:
            date = dt.strptime(sub_string, "%d%m%Y")
        except ValueError:
            continue
        if not (1919 <= date.year <= 2019):
            continue
        return date
    raise ValueError("Date not in the correct format")
票数 7
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/230365

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档