Code that calculates the days between two dates without using the datetime module

0

I am making a code that calculates the days between two dates, however it can not use the datetime module, and it only gives error.

Here is the code:

usuariodata=input()
usuariodata2=input()

Datas=usuariodata.split("/")
Datas1=[int(Datando) for Datando in Datas]

Dia, Mes, Ano = Datas1

MES = Mes-1
NumerosdeDias=0
Contador=1 

while Contador < MES:
    if Contador in (3,5,7,8,10,12):
        NumerosdeDias+=31
    elif Contador in (4,6,9,11):
        NumerosdeDias+=30
    else:
        NumerosdeDias+=28
    Contador+=1

Verifique=(365- NumerosdeDias - Dia - 1)

Datas2=usuariodata2.split("/")
Datas3=[int(Datador) for Datador in Datas2]

Dia1, Mes1, Ano1= Datas3

ANO= Ano1-1
MES1 = Mes1-1
NumeroDeDias=0 
Contadores=1 

while Contadores <= MES1:
  if Contadores in (4,6,9,11):
    NumeroDeDias+=30
  elif Contadores in (1,3,5,7,8,10):
    NumeroDeDias+=31
  else:
    NumeroDeDias+=28
  Contadores+=1
Verificador = (365- NumeroDeDias - Dia1 - 23)

AnoFinal=(Ano1-Ano)
AnoFinal2=AnoFinal*365

if Ano%4 ==0:
  if Mes==2 and Dia==28:
    bissexto=(Ano1-Ano)//4
  else:
    bissexto=(Ano1-Ano)//4-1
elif Ano%4==0:
  if Mes1 ==2:
     bissexto=(Ano1-Ano)//4
  else:
    bissexto=(Ano1-Ano)//4-1
else:
  bissexto=(Ano1-Ano)//4

Verificando = AnoFinal2-bissexto
print(Verifique+Verificador +Verificando)

Link where it can be run: link

    
asked by anonymous 06.02.2017 / 03:42

1 answer

5

Your code has some strange things. The first is about the dubious name chosen for most variables (ex: Datas , Datas1 , Datas2 and Datas3 ). I will rename them. And by renaming, I'll take into account the Python naming convention .

Another problem is with things like this:

Verificador = (365- NumeroDeDias - Dia1 - 23)

Where did this 23 come from?

Ah, it is important to note that, in order to correct a 3-day error that accumulated every 400 years, Pope Gregory XIII determined in 1582 a reform of the calendar that made not every year divisible by 4 be leapt. In this way, 1700, 1800 and 1900 were not leapt. 2100, 2200, and 2300 will not be either. But 1600, 2000 and 2400 are leapt. Your program does not take this into account and therefore misses calculations.

I ran a test with your program and there is clearly something very wrong about it:

 28/02/1900
 01/03/1900
618
 10/10/2010
 11/10/2010
172

Well, let's organize it all. First I noticed this:

if mes in (3, 5, 7, 8, 10, 12):

Where is January? 1 should be there too!

Notice this your if :

if Ano%4 ==0:
    # ...
elif Ano%4==0:

If Ano%4==0 , if enters, but elif does not. Otherwise, neither enters. Anyway, elif never goes in!

You are calculating leap times by subtracting the numbers from years and dividing by 4. This does not work because if you consider a period from 2016 to 2017, the leap day will only count if the beginning is before March 1st. Already in a period from 2015 to 2016, the leap day will count only if the final date is after 29/02. You just check 2/2 specifically, but that's not enough to pick up the leap-day from a period such as 3/8/2015 to 3/8/2016.

To solve the problem I described in the previous paragraph, one way is to count the leap years (and only then), you count for years that start on March 1, as if January and February were the last months instead of being the first. For this, just subtract 1 from the year if it is January or February.

Finally, this% w / w% w / w% w / w can be separated into a function to avoid having to duplicate it. Also I put the whole procedure of calculating the difference of dates in a function.

In case the second date is earlier than the first, to avoid missing math, we can reverse the dates and then consider the negative result.

And finally, to handle cases where the user types invalid dates such as while , if , 32/10/2017 , 29/02/2017 00/00/0000 , 99/99/9999 , etc, I use python exception handling . To help with this process, I created the ab/cd/efgh functions, which determines whether a year is leap year and sorvete-de-abacaxi that determines whether a date is valid or not.

So here's the resulting code:

def dia_no_ano(dia, mes, ano):
  numero_de_dias = dia
  contador_meses = 1
  while contador_meses < mes:
    if contador_meses in (1, 3, 5, 7, 8, 10, 12):
      numero_de_dias += 31
    elif contador_meses in (4, 6, 9, 11):
      numero_de_dias += 30
    elif contador_meses == 2:
      numero_de_dias += 28
    contador_meses += 1
  return numero_de_dias

def bissexto(ano):
  return ano % 4 == 0 and (ano % 100 != 0 or ano % 400 == 0)

def validar_data(dia, mes, ano):
  if dia < 1 or dia > 31 or mes < 1 or mes > 12 or ano < 1583:
    return False
  if mes in (4, 6, 9, 11) and dia == 31:
    return False
  if mes == 2 and dia >= 30:
    return False
  if mes == 2 and dia == 29 and not bissexto(ano):
    return False
  return True

def diferenca_data(data1, data2):

  # Separa os dados adequadamente e trata entradas mal-formadas.
  try:
    dia1, mes1, ano1 = [int(datando) for datando in data1.split("/")]
  except ValueError:
    raise ValueError('Data inválida: ' + data1)

  try:
    dia2, mes2, ano2 = [int(datador) for datador in data2.split("/")]
  except ValueError:
    raise ValueError('Data inválida: ' + data2)

  # Verifica se as datas entradas são válidas:
  if not validar_data(dia1, mes1, ano1):
    raise ValueError('Data inválida: ' + data1)
  if not validar_data(dia2, mes2, ano2):
    raise ValueError('Data inválida: ' + data2)

  # Inverte as datas se a data2 anteceder a data1.
  if ano2 < ano1 or (ano2 == ano1 and (mes2 < mes1 or (mes2 == mes1 and dia2 < dia1))):
    return -diferenca_data(data2, data1)

  # Calcula o número de dias nos anos incompletos.
  dias_ano1 = dia_no_ano(dia1, mes1, ano1)
  dias_ano2 = dia_no_ano(dia2, mes2, ano2)

  # Calcula o número de dias totais, considerando os anos incompletos e anos completos de 365 dias.
  dias_total = dias_ano2 - dias_ano1 + (ano2 - ano1) * 365

  # Considera anos começando em 01/03 para poder fazer a correção dos anos bissextos.
  ano1b = ano1
  if mes1 < 3:
    ano1b -= 1

  ano2b = ano2
  if mes2 < 3:
    ano2b -= 1

  # Soma os dias dos anos bissextos. São os divisíveis por 4 que ocorrem entre ano1b e ano2b.
  dias_total += int(ano2b / 4) - int(ano1b / 4)

  # Subtrai os dias dos anos bissextos que não existiram na etapa anterior. São os divisíveis por 100.
  dias_total -= int(ano2b / 100) - int(ano1b / 100)

  # Soma de volta os dias dos anos bissextos que foram removidos a mais na etapa anterior. São os divisíveis por 400.
  dias_total += int(ano2b / 400) - int(ano1b / 400)

  # Resultado da função.
  return dias_total

####### Início do programa. #######

# Lê a entrada do usuário.
x = input()
y = input()

# Calcula a diferença.
diferenca = diferenca_data(x, y)

# Mostra o resultado.
print(diferenca)

I also did the following tests:

# Testes
print('Testes:')
print(diferenca_data('28/02/1900', '01/03/1900')) # 1 dia.
print(diferenca_data('28/02/1904', '01/03/1904')) # 2 dias.
print(diferenca_data('28/02/2000', '01/03/2000')) # 2 dias.
print(diferenca_data('01/01/2016', '31/12/2016')) # 365 dias.
print(diferenca_data('01/01/2016', '01/01/2017')) # 366 dias.
print(diferenca_data('01/01/2017', '31/12/2017')) # 364 dias.
print(diferenca_data('01/01/2017', '01/01/2018')) # 365 dias.
print(diferenca_data('10/10/2010', '10/10/2410')) # 146097 dias.
print(diferenca_data('01/01/2018', '01/01/2017')) # -365 dias.
print(diferenca_data('01/01/2017', '01/01/2016')) # -366 dias.
print(diferenca_data('01/01/1899', '01/01/1903')) # 1460 dias.
print(diferenca_data('01/01/1900', '01/01/1904')) # 1460 dias.
print(diferenca_data('01/01/1901', '01/01/1905')) # 1461 dias.
print(diferenca_data('01/01/2000', '01/01/2004')) # 1461 dias.

# Datas válidas.
print('Datas válidas:')
print(validar_data(1, 1, 2001))
print(validar_data(1, 1, 1583))
print(validar_data(31, 12, 99999))
print(validar_data(31, 1, 2016))
print(validar_data(28, 2, 1900))
print(validar_data(28, 2, 2017))
print(validar_data(29, 2, 2000))
print(validar_data(29, 2, 2016))
print(validar_data(31, 3, 2016))
print(validar_data(30, 4, 2016))
print(validar_data(31, 5, 2016))
print(validar_data(30, 6, 2016))
print(validar_data(31, 7, 2016))
print(validar_data(31, 8, 2016))
print(validar_data(30, 9, 2016))
print(validar_data(31, 10, 2016))
print(validar_data(30, 11, 2016))
print(validar_data(31, 12, 2016))

# Datas inválidas:
print('Datas inválidas:')
print(validar_data(0, 1, 2001))
print(validar_data(-1, 1, 2001))
print(validar_data(1, 0, 2001))
print(validar_data(1, -1, 2001))
print(validar_data(1, 13, 2001))
print(validar_data(1, 1, 1582))
print(validar_data(32, 1, 2016))
print(validar_data(31, 2, 2016))
print(validar_data(30, 2, 2016))
print(validar_data(29, 2, 1900))
print(validar_data(29, 2, 2017))
print(validar_data(32, 3, 2016))
print(validar_data(31, 4, 2016))
print(validar_data(32, 5, 2016))
print(validar_data(31, 6, 2016))
print(validar_data(32, 7, 2016))
print(validar_data(32, 8, 2016))
print(validar_data(31, 9, 2016))
print(validar_data(32, 10, 2016))
print(validar_data(31, 11, 2016))
print(validar_data(32, 12, 2016))

The output was exactly as expected for all tests.

See all this working in repl.it .

    
06.02.2017 / 07:14