2

有很多关于查找两个日期之间差异的帖子,但所涉及的值以与我使用的格式不同的格式开始和结束,例如:

a = 01/01/10 # dd/mm/yy format
b = 01/01/05 # dd/mm/yy format

因此,我在 a 和 b 之间的年、月和日之间存在差异,其中所需的输出采用格式x years, x months, x days (if required)格式。

我正在阅读datetime 文档,并且想弄清楚它(注意:前面的新手代码,我试图拼凑所有的演示,所以不得不做一些修改):

from datetime import datetime as dt

# calculate duration between two dates

# later date
later_date = '01/01/10'.replace('/', '')
# reverse the order
later_date = "".join(reversed([later_datet[i:i+2] for i in range(0, len(later_date), 2)]))
# separate with commas every two numbers
later_date = ','.join(later_date[i:i+2] for i in range(0, len(later_date), 2))
# convert to datetime object
later_date = dt.strptime(later_date, "%y,%m,%d")

# earlier date
earlier_date = '01/01/05'.replace('/','')
# reverse the order
earlier_date = "".join(reversed([earlier_date[i:i+2] for i in range(0, len(earlier_date), 2)]))
# separate with commas every two numbers
earlier_date = ','.join(earlier_date[i:i+2] for i in range(0, len(earlier_date), 2))
# convert to datetime object
earlier_date = dt.strptime(earlier_date, "%y,%m,%d")

duration = later date - earlier_date

print duration
print type(duration)

正在输出:

1826 days, 0:00:00
<type 'datetime.timedelta'>

所以我认为我有点接近获得正确的数据,但现在我需要将其转换为x years, x months, x days (if required)格式。

编辑/解决方案:

我已经将一些代码放在一起并正在测试,我认为它适用于所有日期组合,但如果有人注意到错误,请告诉我:

"""

this code calculates the duration between two dates (a later and earlier date)
in the format dd/mm/yy and returns the duration in years, months and days with
correct formatting in regards to the plurality of the year/s, month/s, and day/s
and the punctuation required dependent on whether one or more values are returned
ie multiple values are separated by ',' whereas a singular value is terminated by '.'.

"""

# imported libraries
from datetime import datetime as dt
from dateutil import relativedelta
import sys

# initial date objects
later_date = '01/01/10'
earlier_date = '01/01/05'

# convert dates to required format 
a_date = dt.strptime(later_date, '%d/%m/%y')
b_date = dt.strptime(earlier_date, '%d/%m/%y')

# get duration using dateutil
duration = relativedelta.relativedelta(a_date, b_date)

# check if number of years is not false ie != 0
if duration.years != 0:
    years = duration.years
else:
    years = False

# check if number of months is not false ie != 0
if duration.months != 0:
    months = duration.months
else:
    months = False

# check if number of days is not false ie != 0
if duration.days != 0:
    days = duration.days
else:
    days = False

# add values to a list
date_list = [years,months,days]

# count instances of False in the list
false_count = date_list.count(False)

# iterate over list with enumeration performing value and
# boolean checking to predicate plurality and punctuality
# requirements.

for n, _ in enumerate(date_list):
    # year/s - single or plural, lone value or more
    if _ != False and n == 0:
        single_year = date_list[0] == 1
        # if single and not lone
        if single_year == True and false_count != 2:
            sys.stdout.write(str(_)+' year, ')
        # if single and lone
        elif single_year == True and false_count == 2:
            sys.stdout.write(str(_)+' year.')
        # if not single and not lone
        elif single_year == False and false_count != 2:
            sys.stdout.write(str(_)+' years, ')
        # if not single but lone
        elif single_year == False and false_count == 2:
            sys.stdout.write(str(_)+' years.')
    # if there are no years, still provide value for possible later concatenation
    if _ == False and n == 0:
        datasetduration_y = ''
    # month/s - single or plural, lone value or more
    if _ != False and n == 1:
        single_month = date_list[1] == 1
        # if single and not lone
        if single_month == True and false_count != 2:
            sys.stdout.write(str(_)+' month, ')
        # if single and lone
        elif single_month == True and false_count == 2:
            sys.stdout.write(str(_)+' month.')
        # if not single and not lone and there are days
        elif single_month == False and false_count != 2 and date_list[2] != False:
            sys.stdout.write(str(_)+' months, ')
        # if not single and not lone and there are no days
        elif single_month == False and false_count != 2 and date_list[2] == False:
            sys.stdout.write(str(_)+' months.')
        # if not single but lone
        elif single_month == False and false_count == 2:
            sys.stdout.write(str(_)+' months.')
    # if there are no months, still provide value for possible later concatenation
    if _ == False and n == 1:
        datasetduration_m = ''
    # day/s - single or plural, lone value or more
    if _ != False and n == 2:
        single_day = date_list[2] == 1
        # if single and not lone
        if single_day == True and false_count != 2:
            sys.stdout.write(str(_)+' day.')
        # if single and lone
        elif single_day == True and false_count == 2:
            sys.stdout.write(str(_)+' day.')
        # if not single and not lone
        elif single_day == False and false_count != 2:
            sys.stdout.write(str(_)+' days.')
        # if not single but lone
        elif single_day == False and false_count == 2:
            sys.stdout.write(str(_)+' days.')
    # if there are no days, still provide value for possible later concatenation
    if _ == False and n == 2:
        datasetduration_d = ''
4

3 回答 3

0

好吧,我们开始吧。这不是与日期时间相关的解决方案。但是,我认为这仍然应该让你得到你所要求的......

Number of years: 1826/365. 看看已经过去了多少年。

Number of months: (1826%365)/30. 剩下的天数,多少个月。(在这里,我们忽略了特定的月份长度(Jan=31、Feb=28 等),只使用 30 天/月)。

Number of days: (1826%365)%30. 剩余天数,多少天。

于 2013-05-26T10:38:40.660 回答
0

这应该可以解决问题

>>> from datetime import datetime as dt
>>> a = '01/01/2010'
>>> b = '01/01/2005'
>>> a_date = dt.strptime(a, '%d/%m/%Y') # Use capital Y for year with century
>>> b_date = dt.strptime(b, '%d/%m/%Y')
>>> td = a_date - b_date
>>> td
datetime.timedelta(1826)

您现在有一个timedelta对象,其中包含 和 之间的天ab

不太清楚用年、月和日来表达这意味着什么,因为“年”或“月”或“日”都不是标准化的时间单位——年和月的天数和天数是可变的有可变的秒数。在这种情况下,我认为最好以天数表示差异,您可以通过这样做来获得

>>> td.days
1826

如果你真的想表达天数、年数和月数,那么你可以如下操作

>>> nyears = a_date.year - b_date.year
>>> nmonths = a_date.month - b_data.month
>>> ndays = a_date.day - b_data.day

这为您提供了年、日和月的差异,但条件是它们可以是负数。有几个选项可以解决这个问题。一种方法是允许天数、月数和年数的负差异(这在数学上非常有意义)。另一种选择是调整它们:

>>> if ndays < 0:
        ndays = ndays + 30
        nmonths = nmonths - 1
>>> if nmonths < 0:
        nmonths = nmonths + 12
        nyears = nyears - 1
于 2013-05-26T10:46:48.530 回答
0

一个简单的答案:

years, remainder = divmod(duration.days, 365)
months, days = divmod(remainder, 30)
print "{} years, {} months {} days".format(years,months,days)
于 2013-05-26T10:56:36.050 回答