#! /usr/bin/python
# -*- coding:utf8 -*-

'''
Exercice du livre sur Python 3.

Ce code est diffusé sous la licence GPLv3 (http://www.gnu.org/licenses/gpl.html).
Copyright © 2010 Harold Erbin <harold.erbin@gmail.com>
'''

from sys import argv
from datetime import datetime

months = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

today = datetime.today()
today = today.day, today.month, today.year

def bissextile(year):
    '''
    Retourne vrai si l'année passée en argument est bissextile, sinon retourne
    faux.
    '''
    
    return bool((not year % 4 and year % 100) or not year % 400)


# L'argument debug permet de remplacer la date d'aujourd'hui, ce qui permet
# de tester plus simplement les divers cas.

def compute(date_str, debug=None):
    '''
    Cet algorithme renvoie le nombre de jours écoulés entre la date fournie en
    argument (format jour/mois/année) et la date d'aujourd'hui.
    
    Dans cette version, l'idée est de compter directement le nombre de jours
    entre les deux dates. Le programme est légèrement plus compliqué, mais
    il est plus de cent fois plus rapide à exécuter.
    '''
    
    global today
    if debug is not None:
        today = map(int, debug.split('/'))
    
    date = map(int, date_str.split('/'))
    days = 0
    
    # Si les années sont différentes ou si le mois d'aujourd'hui est janvier,
    # et si le mois de la date entrée est après février, et si l'année de la
    # date entrée est bissextile, alors on ajoute un jour.
    if (((date[2] != today[2]) and today[1] > 2) or (date[1] <= 2 < today[1]))\
                and bissextile(date[2]) is True:
        days += 1
    
    # Si les mois sont les mêmes, ou si le jour de la date entrée est inférieur
    # à celui du jour actuel, alors on compte le nombre de jours entre les deux,
    # sinon, on compte le nombre de jours pour aller jusqu'au mois suivant,
    # puis jusqu'au jour considéré.
    if (date[1] == today[1]) or (today[0] > date[0]):
        days += today[0] - date[0]
    else:
        days += months[date[1]-1] - date[0] + today[0]
        # On définit le nouveau mois, afin de ne pas le compter deux fois.
        date[1] += 1
    
    # Si le numéro du mois est inférieur pour la date entrée, on se contente de
    # compter les nombres de jours entre les deux mois, sinon, on compte les
    # jours jusqu'à la nouvelle année, puis jusqu'au mois en cours.
    if date[1] <= today[1]:
        days += sum(months[m-1] for m in range(date[1]-1, today[1]))
    else:
        days += sum(months[m] for m in range(date[1]-1, 12))\
                + sum(months[m] for m in range(0, today[1]-1))
        # On définit la nouvelle année, afin de ne pas la compter deux fois.
        date[2] += 1
    
    # On rajoute maintenant les jours des années entre les deux.
    days += sum((366 if bissextile(a) is True else 365)
                for a in range(date[2], today[2]))
    
    return days

