将python datetime.timedelta转换为dateutil.relativedelta的优雅方式

时间:2013-06-07 06:38:25

标签: python datetime python-datetime python-dateutil

relativedeltatimedelta之间转换是否优雅?

用例是获取用户输入ISO日期。 Python的isodate将返回isodate.duration.Durationdatetime.timedelta

我们需要relativedelta的功能(每What is the difference between "datetime.timedelta" and "dateutil.relativedelta.relativedelta" when working only with days? - 它会更多),因此需要将这两种类型转换为relativedata

3 个答案:

答案 0 :(得分:6)

只需获取secondsmicroseconds的总数,即所有timedelta个对象商店:

def to_relativedelta(tdelta):
    return relativedelta(seconds=int(tdelta.total_seconds()),
                         microseconds=tdelta.microseconds)

>>> to_relativedelta(timedelta(seconds=0.3))
relativedelta(microseconds=+300000)
>>> to_relativedelta(timedelta(seconds=3))
relativedelta(seconds=+3)
>>> to_relativedelta(timedelta(seconds=300))
relativedelta(minutes=+5)
>>> to_relativedelta(timedelta(seconds=3000000))
relativedelta(days=+34, hours=+17, minutes=+20)

答案 1 :(得分:0)

d = datetime.timedelta(...)
dateutil.relativedelta.relativedelta(seconds=d.total_seconds())

答案 2 :(得分:0)

直接在relativedelta中使用秒不会填充月份和年份字段,当然我们不知道它是31天的闰年还是月份。

这样的事情:

[In]:  tdelta = datetime.now() - datetime(1971, 1, 1)
[In]:  relativedelta(seconds=tdelta.total_seconds())
[Out]: relativedelta(days=+16958, hours=+13, minutes=+19, seconds=+49)

给出了相对增量,有很多天,没有几个月。虽然在某些情况下这可能没问题,但在某些情况下我们可能需要数年和数月。因此:

def timedelta_to_relativedelta(tdelta):
    assert isinstance(tdelta, timedelta)

    seconds_in = {
        'year'  : 365 * 24 * 60 * 60,
        'month' : 30 * 24 * 60 * 60,
        'day'   : 24 * 60 * 60,
        'hour'  : 60 * 60,
        'minute': 60
    }

    years, rem = divmod(tdelta.total_seconds(), seconds_in['year'])
    months, rem = divmod(rem, seconds_in['month'])
    days, rem = divmod(rem, seconds_in['day'])
    hours, rem = divmod(rem, seconds_in['hour'])
    minutes, rem = divmod(rem, seconds_in['minute'])
    seconds = rem

    return relativedelta(years=years, months=months, days=days, hours=hours, minutes=minutes, seconds=seconds)

这可能不是一个非常Pythonic的解决方案,但它有效。

注意:这假设一年有365天(忽略跳跃非闰年),月份有30天。