Domanda

I am making a package of functions that gets different values from dates as you can see from the code below. It works, but it sometimes returns values that are off by a small amount.

The code:

    #CALENDAR TOOLS FUNCTIONS
    #CALENDAR INDEXING USES FORMAT: MMM DD, YYYY

    #example: "Aug 17, 1998"

    month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']                
    monthLength = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

    def getMonth(date):
        return date[0:3]

    def getDay(date):
        return int(date[4:6])

    def getYear(date):
        return int(date[8:12])

    def years(a, b):
        a = getYear(a)
        b = getYear(b)
        if a > b:
            return a - b - 1
        else:
            return b - a - 1

    def days(a, b):

        #switches years if start date is past end date
        if (getYear(a) > getYear(b) or
            getYear(a) == getYear(b) and month.index(getMonth(a)) >         month.index(getMonth(b)) or
            getYear(a) == getYear(b) and month.index(getMonth(a)) == month.index(getMonth(b)) and getDay(a) > getDay(b)):
            a, b = b, a

        dayA = getDay(a)
        monthA = getMonth(a)
        yearA = getYear(a)

        dayB = getDay(b)
        monthB = getMonth(b)
        yearB = getYear(b)

        remDays = monthLength[month.index(monthA)] - dayA + 1
        for i in range(month.index(monthA), 11):
            remDays += monthLength[i]

        prevDays = dayB
        for i in range(0, month.index(monthB)):
            prevDays += monthLength[i]

        yearDays = round(years(a, b) * 365.24218967, 0)
        totalDays = yearDays + remDays + prevDays
        return totalDays

When i use the days function with some dates it gets right on some but off a bit on others I will give an example if i input:

days("Jan 01, 2013", "Dec 31, 2015")

for the days I get the correct answer of 1095 days I am getting if it is correct or not from http://www.timeanddate.com/date/duration.html

but when i input:

days("Jan 01, 1908", "Sep 07, 2000")

for the days this time i get 33852 days from the timeanddate.com website i get 33,791 a huge difference and i do not get why

È stato utile?

Soluzione 2

If you are doing it for fun I won't change much what you did. What you are missing (as some people pointed out) is the leap year calculation. Also a couple of details:

1) The first prevDays loop should go from month.index(monthA) + 1 to 12. Remember than range() includes the first arg but excludes the second one, as in: [arg1, arg2).

2) You have an extra + 1 on remDays. It shouldn't be there.

3) You are missing the leap year calculation. You can calculate leap years as

def is_leap_year(year):
    return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

so, on your month loops I'd add:

for i in range(month.index(monthA) + 1, 12):
    remDays += monthLength[i] + (1 if i == 1 and is_leap_year(yearA) else 0)

and

for i in range(0, month.index(monthB)):
    prevDays += monthLength[i] + (1 if i == 1 and is_leap_year(yearB) else 0)

Lastly, you need to add 366 days on leap years instead of 365. So, continuing your loop-style, this would be the year calculation:

yearDays = 0
for year in range(yearA + 1, yearB):
    yearDays += 366 if is_leap_year(year) else 365

Note that this last piece would go instead of your round(..) stuff.

Altri suggerimenti

Your handling of leap years is broken. There are exact rules for leap years, and if you approximate them using your logic (years(a, b) * 365.24218967) you get erroneous results.

Convert your input to a datetime.date() object and use the difference of those.

def days_diff(a, b):
    dta = datetime.date(getYear(a), getMonth(a), getDay(a))
    dtb = datetime.date(getYear(b), getMonth(b), getDay(b))
    return (dta - dtb).days

Edit: Reading your comment that you're doing this for fun and not wanting to use Python's builtin time functions. Then, as Jayanth also commented, take proper care of leap years. Look up the rules when they happen and implement them.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top