Datetime without the year

Asked

Viewed 130 times

2

I need to represent holidays and in my holiday class I need to set the start and end date of the holiday. As start date and end date I need to inform only the month, day, hour and minute. But the class datetime python requires that the year be informed. Is there any way to create an object datetime without the year? Since for holidays the year does not matter. I could create my own datetime class, but as I will need to make date comparisons I would have to overload operators, but I don’t want to have to reinvent the wheel.

class Feriado:
    def __init__(self, start, end):
        self.start = start
        self.end = end

2 answers

4

You can use the function timedelta() standard public datetime to work with a time period instead of working with specific dates, see only:

from datetime import date
from datetime import timedelta

data_inicial = date.today();
data_final = data_inicial + timedelta(days=60);

print( data_inicial )
print( data_final )

Exit:

2018-05-25
2018-07-24

Feriados Móveis such as Easter, Carnival, Good Friday, Ash Wednesday and Corpus Christi depend on the Year to be calculated.

You can use the Algoritmo de Butcher to calculate the Easter holiday, then to calculate the others, see only how would the class Feriado:

from datetime import date
from datetime import timedelta

class Feriado:

    def __init__( self, ano = date.today().year ):
        a = ano % 19
        b = ano // 100
        c = ano % 100
        d = (19 * a + b - b // 4 - ((b - (b + 8) // 25 + 1) // 3) + 15) % 30
        e = (32 + 2 * (b % 4) + 2 * (c // 4) - d - (c % 4)) % 7
        f = d + e - 7 * ((a + 11 * d + 22 * e) // 451) + 114
        mes = f // 31
        dia = f % 31 + 1
        self.data_pascoa = date( ano, mes, dia )
        self.ano = ano

    def ano_novo( self ):
        return date( self.ano, 1, 1 )

    def sexta_feira_santa( self ):
        return self.data_pascoa - timedelta(days=2)

    def cinzas( self ):
        return self.data_pascoa - timedelta(days=46)

    def carnaval( self ):
        return self.data_pascoa - timedelta(days=47)

    def pascoa( self ):
        return self.data_pascoa

    def tirandentes( self ):
        return date( self.ano, 4, 21 )

    def trabalho( self ):
        return date( self.ano, 5, 1 )

    def corpus_christi( self ):
        return self.data_pascoa + timedelta(days=60)

    def independencia( self ):
        return date( self.ano, 9, 7 )

    def nossa_senhora( self ):
        return date( self.ano, 10, 12 )

    def finados( self ):
        return date( self.ano, 11, 2 )

    def proclamacao_republica( self ):
        return date( self.ano, 11, 15 )

    def natal( self ):
        return date( self.ano, 12, 25 )

    def todos( self ):
        return [
            self.ano_novo(),
            self.carnaval(),
            self.cinzas(),
            self.sexta_feira_santa(),
            self.pascoa(),
            self.tirandentes(),
            self.trabalho(),
            self.corpus_christi(),
            self.independencia() ,
            self.nossa_senhora(),
            self.finados(),
            self.proclamacao_republica(),
            self.natal() ]

Checking if today is a holiday:

f = Feriado()

if( date.today() in f.todos() ):
    print( "Hoje eh um Feriado!" )
else:
    print( "Hoje eh um dia util!" )

Calculated Date of Carnival for the year of 2018:

f = Feriado(2018)
print( f.carnaval() )

Listing all holidays of the year 2000:

f = Feriado(2000)
print( f.todos() )
  • The excellent library dateutils also has some very interesting methods related to this and interfaceia well with the datetime. Worth knowing!

  • Yes, I can even use timedelta() for the final date. But I will still have the problem of the year for fixed holidays. For example the holiday of September 7. The year here does not matter, on the day 07/10 00:00 will be the beginning of the holiday and on the day 08/10 00:00 will be the end. The hour and minute is important due to optional holidays that depending on the company, state, city some holidays are extended until half of the next day. And also cases of companies that do not close in some holidays. So in my project the holidays were in charge of the user register them.

2


I could create my own datetime class, but as I will need to make date comparisons I would have to overload operators, but I don’t want to have to reinvent the wheel

Unless you compare dates without a year only with other dates without a year, I don’t see a simple way out of it. It doesn’t have to be complicated, but:

from datetime import datetime

class Feriado(datetime):

    # Na criação de uma nova classe, adicionamos um ano qualquer aos argumentos, para que possamos
    # ser uma classe derivada de datetime.
    def __new__(cls, *args, **kwargs):
        kwargs['year'] = 1970
        return super(Feriado, cls).__new__(Feriado, *args, **kwargs)

    # Fazemos uma cópia do outro datetime ao qual comparamos, mas setamos o ano como o mesmo
    # ano de nosso feriado (assim efetivamente comparamos só dia/mês/hora)
    def __lt__(self, other):
        equivalente = other.replace(year=self.year)
        return super().__lt__(equivalente)

    def __le__(self, other):
        equivalente = other.replace(year=self.year)
        return super().__le__(equivalente)

    def __gt__(self, other):
        equivalente = other.replace(year=self.year)
        return super().__gt__(equivalente)

    def __ge__(self, other):
        equivalente = other.replace(year=self.year)
        return super().__ge__(equivalente)

    def __eq__(self, other):
        equivalente = other.replace(year=self.year)
        return super().__eq__(equivalente)

    def __ne__(self, other):
        equivalente = other.replace(year=self.year)
        return super().__ne__(equivalente)

natal = Feriado(day=25, month=12)
aniversario_florianopolis = Feriado(day=23, month=3)

if natal > datetime.now():
    print('O natal ainda não chegou :(')

if aniversario_florianopolis < datetime.now():
    print('O aniversário de Florianópolis já passou :(')

Browser other questions tagged

You are not signed in. Login or sign up in order to post.