Python 领先 days/weeks/months

Python get days/weeks/months ahead

我一直在通过 Whosebug 搜索答案,但我无法在 Python 中以 Pythonic 方式找到我要找的东西。

我正在尝试根据两个日期提前计算天数、周数或月数。这是我创建的一个小脚本,它可以完成我想做的事情,但我很担心它。

import datetime
from dateutil.relativedelta import relativedelta


now = datetime.datetime.now()
days_ahead = datetime.datetime.now() + relativedelta(days=3)
weeks_ahead = datetime.datetime.now() + relativedelta(weeks=2)
month_ahead = datetime.datetime.now() + relativedelta(months=1)
months_ahead = datetime.datetime.now() + relativedelta(months=3)


def get_relative_date(dt):

    ahead = (dt - now).days

    if ahead < 7:
        return "Due in " + str(ahead) + " days"

    elif ahead < 31:
        return "Due in " + str(ahead/7) + " weeks"

    else:
        return "Due in " + str(ahead/30) + " months"

print get_relative_date(days_ahead)
print get_relative_date(weeks_ahead)
print get_relative_date(month_ahead)
print get_relative_date(months_ahead)

结果如下:

Due in 3 days
Due in 2 weeks
Due in 1 months
Due in 3 months

尽管这是一个很好的答案,但我的担忧与以下方面有关:

提前致谢。如果问题得到回答,请 link 我到 post 我会仔细阅读。如果需要,我愿意提供更多信息。

编辑

我在这里包含了我完整的更新代码,以供在 Python 中也需要此功能的任何人使用。它还处理负日值和今天。

def relative_date(dt):

    if dt is not None and len(dt) > 0:

        now = datetime.now()
        then = arrow.get(dt).naive

        rd = relativedelta(then, now)
        if rd.years or rd.months:
            months = 12 * rd.years + rd.months

            if months < 0:
                if months == -1:
                    return "Due 1 month ago"

                return "Due %i months ago" % -months

            if months == 1:
                return "Due in 1 month"
            return "Due in %d months" % months

        elif rd.days > 7 or rd.days < -7:
            weeks = rd.days / 7

            if weeks < 0:
                if weeks == -1:
                    return "Due 1 week ago"
                return "Due %i weeks ago" % -weeks

            if weeks == 1:
                return "Due in 1 week"
            return "Due in %d weeks" % weeks

        else:

            if rd.days == 0:
                return "Due Today"

            elif rd.days < 0:
                if rd.days == -1:
                    return "Due 1 day ago"
                return "Due %i days ago" % -rd.days

            elif rd.days == 1:
                return "Due in 1 day"

            return "Due in %d days" % rd.days

    else:
        return ""

是的,您当前的代码有问题,因为并非所有月份都有 31 天。在实践中,您可能会认为如果它实际上是在 1 个月零 28 天内到期,但它说“2 个月内到期”并不太重要。毕竟,向下舍入意味着您在 2 个月零 28 天后到期时显示“2 个月内到期”。

因为您使用的是 dateutil module already, note that you can use relativedelta the other way around as well (see the examples page).

如果您用两个日期对象实例化一个 relativedelta,它 returns 一个 relativedelta 对象 yearmonthday属性。

>>> relativedelta(date(2015, 7, 20), date(2014, 6, 10))
relativedelta(years=+1, months=+1, days=+10)

您可以在您的方法中使用它,如下所示:

from dateutil.relativedelta import relativedelta

def get_relative_date(dt):

    rd = relativedelta(dt, now)
    if rd.years or rd.months:
        months = 12 * rd.years + rd.months
        return "Due in %d months" % months
    elif rd.days > 7:
        weeks = rd.days / 7
        return "Due in %d weeks" % weeks
    else:
        return "Due in %d days" % rd.days